diff --git a/Mona-SSC.zip b/Mona-SSC.zip new file mode 100644 index 0000000000000000000000000000000000000000..e501463df707e4a032b2211b01001b7b368e3bd3 Binary files /dev/null and b/Mona-SSC.zip differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/Quick Guide for Working with Unity.pdf b/Mona-SSC/Mona-SSC/MDBNet360_GDP/Quick Guide for Working with Unity.pdf new file mode 100644 index 0000000000000000000000000000000000000000..81b15f12fb31466d9fc72c90a04b30db9aab7979 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/Quick Guide for Working with Unity.pdf differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/.ipynb_checkpoints/Main_Immersive_EDT_RT60-checkpoint.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/.ipynb_checkpoints/Main_Immersive_EDT_RT60-checkpoint.m new file mode 100644 index 0000000000000000000000000000000000000000..0be1c9578033a286da6e2d37f28c3ea3c808cb5d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/.ipynb_checkpoints/Main_Immersive_EDT_RT60-checkpoint.m @@ -0,0 +1,74 @@ +addpath 'RIRs' 'IoSR Toolbox' 'octave' + +%% + +% MR room +%[LS2_sweep, fs2] = audioread("sounds/MR_MDBNet/RIR_MR_Unity_bf.wav"); + +% KT room +%[LS2_sweep, fs2] = audioread("sounds/KT_MDBNet/RIR_KT_Unity_bf.wav"); +%[LS2_sweep, fs2] = audioread("sounds/KT_MDBNet/RIR_KT_gun_Unity_ch1_v2.wav"); + +% UL room +%[LS2_sweep, fs2] = audioread("sounds/UL_MDBNet/RIR_UL_Unity_bf.wav"); + +% ST room +[LS2_sweep, fs2] = audioread("sounds/ST_MDBNet/RIR_ST_Unity_bf.wav"); +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%[sweep, fsst] = audioread("sounds/MR_MDBNet/sine_sweep_16bit.wav"); +%[sweep, fsst] = audioread("sounds/KT_MDBNet/Gunshot-Mono.wav"); +[sweep, fsst] = audioread("sounds/KT_MDBNet/sine_sweep_16bit.wav"); +%[sweep, fsst] = audioread("sounds/UL_MDBNet/sine_sweep_16bit.wav"); +%[sweep, fsst] = audioread("sounds/ST_MDBNet/sine_sweep_16bit.wav"); +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +% MR room +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/MR_MDBNet/RIR_MR_Unity_bf.wav",'graph', true, 'spec', 'full'); + +% KT room +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/KT_MDBNet/RIR_KT_Unity_bf.wav",'graph', true, 'spec', 'full'); +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/KT_MDBNet/RIR_KT_gun_Unity_ch1_v2.wav",'graph', true, 'spec', 'full'); + +% UL room +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/UL_MDBNet/RIR_UL_Unity_bf.wav",'graph', true, 'spec', 'full'); + +% ST room +[RT, DRR, C50, Cfs, EDT] = ... +iosr.acoustics.irStats("sounds/ST_MDBNet/RIR_ST_Unity_bf.wav",'graph', true, 'spec', 'full'); + +% Calculating Mean Values +mean_EDT = mean(EDT(3:8)); +mean_RT = mean(RT(3:8)); + +% MR (done) +%mean_RT = mean(RT(3:8)); +% KT (done) +%mean_RT = mean(RT(3:8)); + +% UL (done) +%mean_RT = mean(RT(3:8)); + +% ST (done) +%mean_RT = mean(RT(3:8)); +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%5 + + +t2 = 0:1/fs2:((length(LS2_sweep)-1)/fs2); + +figure; + +plot(t2,LS2_sweep(:,1).'); xlabel("time [s]"); ylabel("Amplitude"); title("RIR from sweep"); + +% Display Mean Values +disp('Mean RT60:'); +disp(mean_RT); + +disp('Mean EDT:'); +disp(mean_EDT); +%.......................................................................... +%.......................................................................... diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/DTU_ls_dirs_deg.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/DTU_ls_dirs_deg.mat new file mode 100644 index 0000000000000000000000000000000000000000..362bdbc87fe96071cd548fc8afb54bf9b5d79607 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/DTU_ls_dirs_deg.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/EarlyScatter.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/EarlyScatter.m new file mode 100644 index 0000000000000000000000000000000000000000..354416be749b0191b98a033ce300cdaab31ab7dc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/EarlyScatter.m @@ -0,0 +1,35 @@ + + +% Script file to plot an example of a RIR signal with clusters around the +% early reflection peaks + +% We consider N=4 reflections at N times & directions (theta & phi) + +Ttime = [10, 32, 54, 87]; + +rnd = round(10*randn(4,10)); + +times_mat = Ttime'+ rnd; +figure; plot(abs(times_mat(:)),ones(1,length(times_mat(:))),'-*'); + +Theta = [35, 55, 105, 160]; + +rnd = round(10*randn(4,10)); + +theta_mat = Theta'+ rnd; +figure; plot(abs(theta_mat(:)),ones(1,length(theta_mat(:))),'-*'); + +phi = [0, 20, 35, 85]; + +rnd = round(5*randn(4,10)); + +phi_mat = phi'+ rnd; +figure; plot(abs(phi_mat(:)),ones(1,length(phi_mat(:))),'-*'); + +amp = [10, 6, 3, 8]; +rnd = round(2*randn(4,10)); + +amp_mat =(amp'+ rnd); +figure; plot(abs(amp_mat(:)),'-*'); +figure; scatter3(abs(theta_mat(:)),abs(phi_mat(:)),abs(times_mat(:)),5*abs(amp_mat(:)),'filled'); +xlabel('\theta'); ylabel('\phi'); zlabel('time') diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox.prj b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox.prj new file mode 100644 index 0000000000000000000000000000000000000000..2c25508c09bf5cf598f6c0bae7c5cd69aa29ec63 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox.prj @@ -0,0 +1,160 @@ +<deployment-project plugin="plugin.toolbox" plugin-version="1.0"> + <configuration file="C:\Users\aa2r22\OneDrive - University of Southampton\Ati Spatial Audio 2022 ECS RF Uni of Soton\Matlab files\IoSR Toolbox.prj" location="C:\Users\aa2r22\OneDrive - University of Southampton\Ati Spatial Audio 2022 ECS RF Uni of Soton\Matlab files" name="IoSR Toolbox" target="target.toolbox" target-name="Package Toolbox"> + <param.appname>IoSR Toolbox</param.appname> + <param.authnamewatermark /> + <param.email /> + <param.company /> + <param.summary /> + <param.description /> + <param.screenshot /> + <param.version>1.0</param.version> + <param.output>${PROJECT_ROOT}\IoSR Toolbox.mltbx</param.output> + <param.products.name /> + <param.products.id /> + <param.products.version /> + <param.platforms /> + <param.guid>03d738cc-04db-4f94-aeda-17a2b7117eba</param.guid> + <param.exclude.filters /> + <param.exclude.pcodedmfiles>true</param.exclude.pcodedmfiles> + <param.examples /> + <param.demosxml /> + <param.apps /> + <param.registered.apps /> + <param.docs /> + <param.getting.started.guide /> + <param.matlabpath.excludes /> + <param.javaclasspath.excludes /> + <param.exported.on.package>false</param.exported.on.package> + <param.required.addons /> + <param.matlab.project.id /> + <param.matlab.project.name /> + <param.release.start /> + <param.release.end /> + <param.release.current.only>false</param.release.current.only> + <param.compatiblity.windows>true</param.compatiblity.windows> + <param.compatiblity.macos>true</param.compatiblity.macos> + <param.compatiblity.linux>true</param.compatiblity.linux> + <param.compatiblity.matlabonline>true</param.compatiblity.matlabonline> + <param.installation.map /> + <param.additional.sw.names /> + <param.additional.sw.licenses /> + <param.additional.sw.win.url /> + <param.additional.sw.mac.url /> + <param.additional.sw.linux.url /> + <unset> + <param.authnamewatermark /> + <param.email /> + <param.company /> + <param.summary /> + <param.description /> + <param.screenshot /> + <param.version /> + <param.output /> + <param.products.name /> + <param.products.id /> + <param.products.version /> + <param.platforms /> + <param.exclude.filters /> + <param.exclude.pcodedmfiles /> + <param.examples /> + <param.demosxml /> + <param.apps /> + <param.registered.apps /> + <param.docs /> + <param.getting.started.guide /> + <param.matlabpath.excludes /> + <param.javaclasspath.excludes /> + <param.exported.on.package /> + <param.required.addons /> + <param.matlab.project.id /> + <param.matlab.project.name /> + <param.release.start /> + <param.release.end /> + <param.release.current.only /> + <param.compatiblity.windows /> + <param.compatiblity.macos /> + <param.compatiblity.linux /> + <param.compatiblity.matlabonline /> + <param.installation.map /> + <param.additional.sw.names /> + <param.additional.sw.licenses /> + <param.additional.sw.win.url /> + <param.additional.sw.mac.url /> + <param.additional.sw.linux.url /> + </unset> + <fileset.rootdir> + <file>${PROJECT_ROOT}\IoSR Toolbox</file> + </fileset.rootdir> + <fileset.rootfiles> + <file>${PROJECT_ROOT}\IoSR Toolbox\+iosr</file> + <file>${PROJECT_ROOT}\IoSR Toolbox\.gitignore</file> + <file>${PROJECT_ROOT}\IoSR Toolbox\deps</file> + <file>${PROJECT_ROOT}\IoSR Toolbox\LICENSE</file> + <file>${PROJECT_ROOT}\IoSR Toolbox\README.md</file> + <file>${PROJECT_ROOT}\IoSR Toolbox\release-notes.md</file> + </fileset.rootfiles> + <fileset.depfun.included /> + <fileset.depfun.excluded /> + <fileset.package /> + <build-deliverables> + <file location="${PROJECT_ROOT}" name="IoSR Toolbox.mltbx" optional="false">C:\Users\aa2r22\OneDrive - University of Southampton\Ati Spatial Audio 2022 ECS RF Uni of Soton\Matlab files\IoSR Toolbox.mltbx</file> + </build-deliverables> + <workflow /> + <matlab> + <root>C:\Program Files\MATLAB 2021a</root> + <toolboxes> + <toolbox name="matlabcoder" /> + <toolbox name="embeddedcoder" /> + <toolbox name="gpucoder" /> + <toolbox name="fixedpoint" /> + <toolbox name="matlabhdlcoder" /> + <toolbox name="neuralnetwork" /> + </toolboxes> + <toolbox> + <matlabcoder> + <enabled>true</enabled> + </matlabcoder> + </toolbox> + <toolbox> + <embeddedcoder> + <enabled>true</enabled> + </embeddedcoder> + </toolbox> + <toolbox> + <gpucoder> + <enabled>true</enabled> + </gpucoder> + </toolbox> + <toolbox> + <fixedpoint> + <enabled>true</enabled> + </fixedpoint> + </toolbox> + <toolbox> + <matlabhdlcoder> + <enabled>true</enabled> + </matlabhdlcoder> + </toolbox> + <toolbox> + <neuralnetwork> + <enabled>true</enabled> + </neuralnetwork> + </toolbox> + </matlab> + <platform> + <unix>false</unix> + <mac>false</mac> + <windows>true</windows> + <win2k>false</win2k> + <winxp>false</winxp> + <vista>false</vista> + <linux>false</linux> + <solaris>false</solaris> + <osver>10.0</osver> + <os32>false</os32> + <os64>true</os64> + <arch>win64</arch> + <matlab>true</matlab> + </platform> + </configuration> +</deployment-project> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+acoustics/irStats.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+acoustics/irStats.m new file mode 100644 index 0000000000000000000000000000000000000000..6c22b687cb0f6ed9a1c67373d908d7b0c398faac --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+acoustics/irStats.m @@ -0,0 +1,355 @@ + +function [rt,drr,cte,cfs,edt] = irStats(filename,varargin) +%IRSTATS Calculate RT, DRR, Cte, and EDT for impulse response file +% +% RT = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the reverberation time +% (to -60 dB) using a method based on ISO 3382-1:2009. The function uses +% reverse cumulative trapezoidal integration to estimate the decay curve, +% and a linear least-square fit to estimate the slope between 0 dB and +% -60 dB. Estimates are taken in octave bands and the overall figure is +% an average of the 500 Hz and 1 kHz bands. +% +% FILENAME should be the full path to an audio file or the name of an +% audio file on the Matlab search path. The file can be of any format +% supported by the AUDIOREAD function, and have any number of channels; +% estimates (and plots) will be returned for each channel. +% +% The function returns a 1xN vector of RTs, where N is the number of +% channels in the audio file. +% +% The function determines the direct sound as the peak of the squared +% impulse response. +% +% [RT,DRR] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% direct-to-reverberant-ratio DRR for the impulse; DRR is a 1xN vector. +% This is calculated in the following way: +% +% DRR = 10 * log10( X(T0-C:T0+C)^2 / X(T0+C+1:end)^2 ) +% +% where X is the approximated integral of the impulse, T0 is the time of +% the direct impulse, and C=2.5ms [1]. +% +% [RT,DRR,CTE] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% early-to-late index CTE for the impulse; CTE is a 1xN vector. +% This is calculated in the following way: +% +% CTE = 10 * log10( X(T0-C:T0+TE)^2 / X(T0+TE+1:end)^2 ) +% +% where TE is 50 ms. +% +% [RT,DRR,CTE,CFS] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% octave-band centre frequencies CFS used in the calculation of RT. +% +% [RT,DRR,CTE,CFS,EDT] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% early decay time EDT, which is the same size as RT. The slope of the +% decay curve is determined from the fit between 0 and -10 dB. The decay +% time is calculated from the slope as the time required for a 60 dB +% decay. +% +% ... = IOSR.ACOUSTICS.IRSTATS(...,'PARAMETER',VALUE) allows numerous +% parameters to be specified. These parameters are: +% +% 'graph' : {false} | true +% Controls whether decay curves are plotted. Specifically, graphs +% are plotted of the impulse response, decay curves, and linear +% least-square fit for each octave band and channel of the audio +% file. If the EDT output is specified, the EDT fit will also be +% plotted. +% 'te' : {0.05} | scalar +% Specifies the early time limit (in seconds). +% 'spec' : {'mean'} | 'full' +% Determines the nature of RT and EDT outputs. With spec='mean' +% (default) the reported RT and EDT are the mean of the 500 Hz +% and 1 kHz bands. With spec='full', the function returns the +% RT and EDT as calculated for each octave band returned in +% CFS; RT and EDT have size [M N] where M=length(CFS). +% 'y_fit' : {[0 60]} | two-element vector +% Specifies the decibel range over which the decay curve should +% be evaluated. For example, 'y_fit' may be [-5 -25] or [-5 -35] +% corresponding to the RT20 and RT30 respectively. +% 'correction' : {0.0025} | scalar +% Specifies the correction parameter C (in seconds) given above +% for DRR and CTE calculations. Values of up to 10 ms have been +% suggested in the literature. +% +% Octave-band filters are calculated according to ANSI S1.1-1986 and IEC +% standards. Note that the OCTDSGN function recommends centre frequencies +% fc in the range fs/200 < fc < fs/5. +% +% The author would like to thank Feifei Xiong for his input on the +% correction parameter. +% +% References +% +% [1] Zahorik, P., 2002: 'Direct-to-reverberant energy ratio +% sensitivity', The Journal of the Acoustical Society of America, +% 112, 2110-2117. +% +% See also AUDIOREAD, OCTDSGN. + +% Copyright 2016 University of Surrey. + + %% validate inputs and set options + + % check dependency + if exist('octdsgn','file')~=2 + web('http://uk.mathworks.com/matlabcentral/fileexchange/69-octave','-new','-browser') + error('iosr:irStats:OctaveToolbox','Please download and install the OCTAVE toolbox from: http://uk.mathworks.com/matlabcentral/fileexchange/69-octave') + end + + % check file exists + assert(exist(filename,'file')==2, 'iosr:irStats:invalidFile', ['iosr.acoustics.irStats: ' filename ' does not exist']) + + % set defaults + options = struct(... + 'graph',false,... + 'te',0.05,... + 'spec','mean',... + 'y_fit',[0 -60],... + 'correction',0.0025); + + % read parameter/value inputs + if nargin>1 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:irStats:nameValuePair','IRSTATS needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:irStats:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % check options size and type + assert(isvector(options.y_fit) && numel(options.y_fit)==2, 'iosr:irStats:invalidYfit', '''y_fit'' must be a two-element vector.') + assert(isscalar(options.correction), 'iosr:irStats:invalidCorrection', '''correction'' must be a scalar.') + assert(isscalar(options.te), 'iosr:irStats:invalidTe', '''te'' must be a scalar.') + assert(ischar(options.spec), 'iosr:irStats:invalidSpec', '''spec'' must be a char array.') + assert(islogical(options.graph) && numel(options.graph)==1, 'iosr:irStats:invalidGraph', '''graph'' must be logical.') + + % check for reasonable values + assert(all(options.y_fit<=0), 'iosr:irStats:invalidYfit', '''y_fit'' values must be less than or equal to 0.') + assert(options.te>=0, 'iosr:irStats:invalidTe', '''te'' must be greater than or equal to 0.') + assert(options.correction>=0, 'iosr:irStats:invalidCorrection', '''correction'' must be greater than or equal to 0.') + + %% read in audio file + + % read in impulse + [x,fs] = audioread(filename); + assert(fs>=5000, 'iosr:irStats:invalidFs', 'Sampling frequency is too low. FS must be at least 5000 Hz.') + assert(sum(abs(x(:)))>0, 'iosr:irStats:silence', 'The signal appears to be silent.') + + % set te in samples + te = round(options.te*fs); + + % Check sanity of te + assert(te<length(x), 'iosr:irStats:invalidTe', 'The specified early time limit te is longer than the duration of the impulse!') + + % get number of channels + numchans = size(x,2); + + %% set up octave-band filters +%.......................................................................... + % octave-band center frequencies + %cfs = [31.25 62.5 125 250 500 1000 2000 4000 8000 16000]; + + % octave-band filter order + N = 3; + + % limit centre frequencies so filter coefficients are stable + %cfs = cfs(cfs>fs/200 & cfs<fs/5); + %cfs = cfs(:); +% + % Modified by Atiyeh 07/02/2023 03:33 pm. following the RSAO cfs + cfs = 1000*2.^(-4:4); +%.......................................................................... + % calculate filter coefficients + a = zeros(length(cfs),(2*N)+1); + b = zeros(length(cfs),(2*N)+1); + for f = 1:length(cfs) + [b(f,:),a(f,:)] = octdsgn(cfs(f),fs,N); + end + + %% perform calculations + + % empty matrices to fill + z = zeros([length(cfs) size(x)]); + rt_temp = zeros([length(cfs) numchans]); + edt = zeros([length(cfs) numchans]); + t0 = zeros(1,numchans); + drr = zeros(1,numchans); + cte = zeros(1,numchans); + + correction = round(options.correction*fs); + + % filter and integrate + for n = 1:numchans + % find direct impulse + peak = find(x(:,n).^2==max(x(:,n).^2)); + if numel(peak)>1 + warning('iosr:irStats:multiplePeaks','More than one peak found. Choosing first peak. Are you sure this is an impulse response?') + end + t0(n) = peak(1); + % draw figure + if options.graph + scrsz = get(0,'ScreenSize'); + figpos = [((n-1)/numchans)*scrsz(3) scrsz(4) scrsz(3)/2 scrsz(4)]; + % figure('Name',['Channel ' num2str(n)],'OuterPosition',figpos); + figure('Name',['Channel ' num2str(n)]); + end + % evaluate impulse in each octave band + + for f = 1:length(cfs) + y = filter(b(f,:),a(f,:),x(:,n)); % octave-band filter + temp = cumtrapz(y(end:-1:1).^2); % decay curve + z(f,:,n) = temp(end:-1:1); + [rt_temp(f,n),E_rt,fit_rt] = calc_decay(z(f,t0:end,n),options.y_fit,60,fs,cfs(f)); % estimate RT + %[rt_temp(f,n),E_rt,fit_rt] = calc_decay(z(f,t0:end,n),[-5, -25],60,fs,cfs(f)); % estimate RT % in case of artifacts (UL room)-->try T20 [-5 -25] or T30[-5 -35] + [edt(f,n),E_edt,fit_edt] = calc_decay(z(f,t0:end,n),[0,-10],60,fs,cfs(f)); % estimate EDT + if options.graph % plot + % time axes for different vectors + %ty = ((0:length(y)-1)-t0(n))./fs; + ty = (0:length(y)-1)./fs; + tE_rt = (0:length(E_rt)-1)./fs; + tE_edt = (0:length(E_edt)-1)./fs; + + % plot + subplot(length(cfs),2,(2*f)-1) + plot(ty,y,'k') % octave-band impulse + if f==1 + title({'Impulse response'; ''; [num2str(cfs(f)) ' Hz octave band']}) + else + title([num2str(cfs(f)) ' Hz octave band']) + end + if f==length(cfs) + xlabel('Time [s]') + else + set(gca,'xticklabel',[]); + end + ylabel('Amplitude') + set(gca,'position',[1 1 1 1.05].*get(gca,'position'),'xlim',[min(ty) max(ty)]); + subplot(length(cfs),2,2*f) + % energy decay and linear least-square fit + if nargout==5 + % plot EDT fit if EDT wanted + plot(tE_rt,E_rt,'-k',tE_rt,fit_rt,'--r',tE_edt,fit_edt,':b') + else + plot(tE_rt,E_rt,'-k',tE_rt,fit_rt,'--r') + end + % title for top row + if f==1 + title({'Decay curve'; ''; [num2str(cfs(f)) ' Hz octave band']}) + else + title([num2str(cfs(f)) ' Hz octave band']) + end + % x label for bottom row + if f==length(cfs) + xlabel('Time [s]') + else + set(gca,'xticklabel',[]); + end + ylabel('Energy [dB]') + set(gca,'position',[1 1 1 1.05].*get(gca,'position'),'ylim',[-70 0],'xlim',[0 max(tE_rt)]); + % choose legend according to EDT request + fitstr = num2str(abs(diff(options.y_fit))); + if nargout==5 + legend('Energy decay curve',['Linear fit (RT' fitstr ')'],'Linear fit (EDT)','location','northeast') + else + legend('Energy decay curve',['Linear fit (RT' fitstr ')'],'location','northeast') + end + end + end + + + + % DRR + if nargout>=2 + drr(n) = 10.*log10(... + trapz(x(max(1,t0(n)-correction):t0(n)+correction,n).^2)/... + trapz(x(t0(n)+correction+1:end,n).^2)... + ); + end + % Cte + if nargout>=3 + if t0(n)+te+1>size(x,1) + warning('iosr:irStats:teOutOfRange',['Early time limit (te) out of range in channel ' num2str(n) '. Try lowering te.']) + cte(n) = NaN; + else + cte(n) = 10.*log10(... + trapz(x(max(1,t0(n)-correction):t0(n)+te).^2)/... + trapz(x(t0(n)+te+1:end,n).^2)... + ); + end + end + end + + %% write output + + switch lower(options.spec) + case 'full' + rt = rt_temp; + case 'mean' + rt = mean(rt_temp(cfs==500 | cfs==1000,:)); % overall RT + edt = mean(edt(cfs==500 | cfs==1000,:)); % overall EDT + otherwise + error('iosr:irStats:unknownSpec','Unknown ''spec'': must be ''full'' or ''mean''.') + end + +end + +function [t,E,fit] = calc_decay(z,y_fit,y_dec,fs,f) +% CALC_DECAY calculate decay time from decay curve +% Returns the time for a specified decay y_dec calculated +% from the fit over the range y_fit. The input is the +% integral of the impulse sample at fs Hz. The function also +% returns the energy decay curve in dB and the corresponding +% fit. + + E = 10.*log10(z); % put into dB + E = E-max(E); % normalise to max 0 + + if any(isinf(E)) + E = E(1:find(isinf(E),1,'first')-1); % remove trailing infinite values + end + + % find yfit x-range + IX1 = findDB(E,max(y_fit),1,f); + IX2 = findDB(E,min(y_fit),length(E),f); + IX = IX1:IX2; + + % calculate fit over yfit + diff_y = abs(diff(y_fit)); % dB range diff + x = reshape(IX,1,length(IX)); + y = reshape(E(IX),1,length(IX)); + p = polyfit(x,y,1); + fitLength = max(length(E),(1.1*diff_y/abs(length(E)*p(1)))*length(E)); % evaluate fit over sufficient dynamic range + fit = polyval(p,1:fitLength); % actual fit + fit0 = fit-max(fit); % fit anchored to 0dB + t = (y_dec/diff_y)*findDB(fit0,-diff_y,[],f)/fs; % estimate decay time + fit = fit(1:length(E)); + +end + +function IX = findDB(E,dB,default,f) +% FINDDB find dB value in energy decay + + IX = find(E<=dB,1,'first'); + if isempty(IX) + if isempty(default) + error('iosr:irStats:dynamicRange','Impulse response has insufficient dynamic range at %i Hz to evaluate at %i dB.',f,dB) + else + warning('iosr:irStats:dynamicRange''Impulse response has insufficient dynamic range at %i Hz to evaluate at %i dB. Evaluating at %.1f dB instead.',f,dB,E(default)) + IX = default; + end + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+acoustics/rtEst.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+acoustics/rtEst.m new file mode 100644 index 0000000000000000000000000000000000000000..4fde07a46bacb8084b70f5f5d3d25c405d02bb90 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+acoustics/rtEst.m @@ -0,0 +1,39 @@ +function rt = rtEst(abs_coeff,room,formula) +%RTEST Estimate reverberation time based on room size and absorption +% +% RT = IOSR.ACOUSTICS.RTEST(ABS_COEFF,ROOM) estimates the reverberation +% time (RT60) for a shoebox-shaped room, with average absorption +% coefficient ABS_COEFF, and dimenions ROOM=[L W H] (in metres). An RT +% estimate is returned for each element of ABS_COEFF. +% +% RT = IOSR.ACOUSTICS.RTEST(ABS_COEFF,ROOM,FORMULA) allows the formula to +% be specified. The options are 'sabine' (default), or 'eyring'. + +% Copyright 2016 University of Surrey. + + assert(isnumeric(abs_coeff), 'iosr:rtEst:invalidCoeff', 'abs_coeff should be numeric') + assert(isnumeric(room) & numel(room)==3 & isvector(room), 'iosr:rtEst:invalidRoom', 'room should be a 3-element numeric vector') + + if nargin<3 + formula = 'sabine'; + end + + assert(ischar(formula), 'iosr:rtEst:invalidFormula', 'formula should be a character array (string)') + + l = room(1); + w = room(2); + h = room(3); + + vol = prod(room); + surf_area = (2*l*w) + (2*l*h) + (2*w*h); + + switch lower(formula) + case 'sabine' + rt = (0.161*vol)./(surf_area.*abs_coeff); + case 'eyring' + rt = (0.161*vol)./(-surf_area.*log(1-abs_coeff)); + otherwise + error('iosr:rtEst:unknownFormula','Unknown formula') + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/azimuth2itd.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/azimuth2itd.m new file mode 100644 index 0000000000000000000000000000000000000000..4a1b03a4f13a4c8dbc6aa10d1a82eaf8e7fc80c6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/azimuth2itd.m @@ -0,0 +1,26 @@ +function itd = azimuth2itd(azimuth,f) +%AZIMUTH2ITD Convert azimuth in degrees to ITD +% +% ITD = IOSR.AUDITORY.AZIMUTH2ITD(AZIMUTH,F) converts the azimuth AZIMUTH +% in degrees at frequency F to interaural time difference according to +% Kuhn's model [1]. +% +% References +% +% [1] Kuhn, G.F. (1977), Model for the interaural time differences in the +% azimuthal plane, The Journal of the Acoustical Society of America +% 62, 1, 157-167. +% +% See also IOSR.AUDITORY.ITD2AZIMUTH, IOSR.AUDITORY.FREQMULTI. + +% Copyright 2016 University of Surrey. + + assert(isnumeric(azimuth), 'iosr:azimuth2itd:invalidInput', 'AZIMUTH must be numeric') + assert((isscalar(f) | isscalar(azimuth)) | numel(f)==numel(azimuth),... + 'iosr:azimuth2itd:invalidInput', ... + 'F or ITD must be a scalar, or F and AZIMUTH must be the same size') + + czero = 344; + itd = (iosr.auditory.freqMulti(f).*0.091.*sind(azimuth))./czero; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/binSearch.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/binSearch.m new file mode 100644 index 0000000000000000000000000000000000000000..b5e29dab55d3732e6010e103bd9b3caa8d8c5acf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/binSearch.m @@ -0,0 +1,97 @@ +% Conduct a binary search +% +% binSearch: Conducts a binary search and continues until the score is +% close enough to the target. An upper limit should be set on the number of +% iterations +% +% [SearchPoint, Step, ReLoop] = iosr.auditory.binSearch(Score, ... +% TargetScore, ... +% CloseEnough, ... +% NextSearchPointa, ... +% Step, ... +% LoopCount, ... +% MaxLoops); +% end +% +% inputs: +% - Score: the test value +% - Target: the 'finished' test value +% - CloseEnough: the distance from the Target at which it is acceptable to +% discontinue the binary search +% - SearchPoint: the next work input value to try +% - Step: the distance which the SearchPoint can move by +% - LoopCount: a counter for the number of iterations completed so far +% - MaxLoops: The upper limit on the number of iterations allowed +% +% outputs: +% - SearchPoint: the next work input value you should try +% - Step: the distance which can be stepped on the NEXT iteration. You +% should store this value. +% - ReLoop: If this flag is set to 0, the upper level while loop will be +% terminated +% +% +% example: you wish to use an audibility model to find the level at which +% you can be 50% confident of detecting the signal (-+ 1%). You choose to +% start with an input level of 20dB and take no more than 10 steps of +% 40,20,10 dB etc. +% +% You would implement this in the following way: +% +% TargetPercent = 0.5; +% CloseEnough = 0.01; +% Signal Level = 40; +% Step = 40; +% MaxLoops = 10; +% LoopCount = 0; +% +% while ReLoop = 1 +% +% LoopCount = LoopCount + 1; +% +% Percent = RunAudibilityModel(SignalLevel) +% +% [SignalLevel Step ReLoop] = iosr.auditory.binSearch(Percent, ... +% TargetPercent, ... +% CloseEnough, ... +% SignalLevel, ... +% Step, ... +% LoopCount, ... +% MaxLoops); +% +% end +% + +% Copyright 2016 University of Surrey. + +function [SearchPoint, Step, ReLoop] = binSearch(Score, Target, CloseEnough, SearchPoint, Step, LoopCount, MaxLoops) + +% input tests +% test input types +assert(isnumeric(Score) ... + &isnumeric(Target) ... + &isnumeric(CloseEnough) ... + &isnumeric(SearchPoint) ... + &isnumeric(Step) ... + &isnumeric(LoopCount) ... + &isnumeric(MaxLoops),'input arguments must be numeric!'); + + +% Define next search point +if Score > Target + SearchPoint = SearchPoint - Step; +else + SearchPoint = SearchPoint + Step; +end + +% half the distance of the next step +Step = Step / 2; + +% if we got close enough to our taget, or it was the last iteration +if (abs((Score-Target))<CloseEnough)||(LoopCount>=MaxLoops) + ReLoop = 0; +else + ReLoop = 1; +end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/calcIld.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/calcIld.m new file mode 100644 index 0000000000000000000000000000000000000000..01337e8747fbebe0bfe41255948d0ec335c391ed --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/calcIld.m @@ -0,0 +1,56 @@ +function ild = calcIld(L,R,method) +%CALCILD Calculate normalised interaural level difference +% +% ILD = IOSR.AUDITORY.CALCILD(L,R) calculates the ILD of vectors L and R. +% Rather than a logarithmic ratio, the returned ILD is in the range +% [-1,1]. The algorithm has the following steps: +% +% 1. Calculate total power for each L and R vectors. +% 2. Calculate difference of powers and divide by power sum. +% 3. Square result, ensuring sign is retained. This improves contrast +% when the signals are of a similar level. +% +% ILD = IOSR.AUDITORY.CALCILD(L,R,METHOD) determines the nature of the +% ILD that is returned, and consequently how it is calculated. When +% method is 'overall' (default), the ILD for the entire signal is +% returned, based on the power carried by the fine structure. When method +% is 'vector', the ILD is calculated using the instaneous Hilbert +% envelope and the function returns a vector the same size as L or R. +% +% The function is derived from Ben Supper's thesis "An onset-guided +% spatial analyser for binaural audio" + +% Copyright 2016 University of Surrey. + + assert(isvector(L) & isvector(R), 'iosr:calcIld:invalidInput', 'L and R must be vectors') + assert(all(size(L)==size(R)), 'iosr:calcIld:invalidInput', 'L and R must be the same size') + + if nargin<3 + method='overall'; + else + assert(ischar(method), 'iosr:calcIld:invalidMethod', 'METHOD must be a string.') + end + + switch lower(method) + case 'vector' + envL = calc_env(L); + envR = calc_env(R); + p_L = envL.^2; + p_R = envR.^2; + case 'overall' + p_L = sum(L.^2); + p_R = sum(R.^2); + otherwise + error('iosr:calcIld:unknownMethod',['Unknown method ''' method '''.']) + end + ild = (p_L-p_R)./(p_L+p_R); + ild = sign(ild).*(ild.^2); + + end + +function y = calc_env(x) +%CALC_ENV return signal Hilbert envelope + + y = abs(hilbert(x)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr.m new file mode 100644 index 0000000000000000000000000000000000000000..c463ff865b250e5d1c6226bc3ed22af748f978aa --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr.m @@ -0,0 +1,250 @@ +function [ccg,ic] = chXcorr(hc_L,hc_R,fs,varargin) +%CHXCORR Calculate cross-correlograms with a wide range of options. +% +% CCG = IOSR.AUDITORY.CHXCORR(HC_L,HC_R,FS) cross-correlates the input +% 2-D matrices HC_L and HC_R over 10ms frame with a maximum lag of 1ms. +% It is assumed that the number of frequency channels is min(size(HC_L)) +% and hence HC_L and HC_R can be in either orientation. The +% cross-correlograms consist of cross-correlations for every frame and +% frequency channel. CCG has dimensions [lag,frequency,frame]. The +% function calculates running cross-correlations for every sample and +% integrates these cross-correlations over each frame. The number of +% frames frame_count is calculated thus: +% +% frame_count = ... +% floor((max(size(hc_L))-maxlag-1)/frame_length); +% +% The underlying cross-correlation algorithm is based on that proposed by +% Faller & Merimaa [1]. In this implmentation, the time constant of the +% backward infinite exponential window is given by tau (in samples). +% +% CCG = IOSR.AUDITORY.CHXCORR(HC_L,HC_R,FS,'PARAMETER',VALUE) allows a +% number of options to be specified. The options are: +% +% ({} indicates the default value) +% +% 'frame_length' : {round(0.01*fs)} | scalar +% The length of frames used to calculate for integrating +% cross-correlations. +% 'noverlap' : {1} | scalar +% The number of frames over which to integrate the +% cross-correlations. Note that the frame count is reduced +% accordingly. +% 'maxlag' : {round(0.001*fs)} | scalar +% The maximum lag of the cross-correlation. +% 'tau' : {round(0.01*fs)} | scalar +% The time constant of the exponential window used to calculate +% running cross-correlations. It is recommended that if norm_flag = 1 +% then tau >> 1. As can be seen below, as tau -> 1 then +% [aL(m,i,n?1), aR(m,i,n?1)] -> 0, and hence c(m,i,n) -> 1. +% 'inhib' : {[]} | array +% Specificies an array with which to multiply the cross-correlations +% before they are integrated. The value defaults to an empty array, +% meaning that no inhibition will be applied. +% 'ic_t' : {0} | scalar +% Specifies the interaural coherence (IC) threshold. Only samples for +% which the IC exceeds this threshold will be used to integrate +% cross-correlations. The algorithm calculates Interaural Coherence +% (IC) according to [1]. The value should be in the range [0,1]. +% 'norm_flag' : {0} | scalar +% Specifies whether the cross-correlograms are calculated using +% normalised cross-correlations. A non-zero value indicates that +% normalised cross-correlations are used. +% 'inhib_mode' : {'subtract'} | 'multiply' +% Specify how the inhibition is applied. The default 'subtract' will +% subtract inhib from the running cross-correlations (negative values +% are set to zero); 'multiply' will multiply inhib with the running +% cross-correlations. +% +% [CCG,IC] = IOSR.AUDITORY.CHXCORR(...) returns the calculated IC to the +% matrix IC. Although the matrix returned is the same size as hc_L, IC is +% only calculated for samples 1:frame_count*frame_length, other values +% will be set to 0. +% +% Algorithm +% +% The running normalised cross-correlation is calculated as [1]: +% +% C(m,i,n) = c(m,i,n) / sqrt( aL(m,i,n) * aR(m,i,n) +% +% where +% +% c(m,i,n) = (1/tau) * HC_L(i, max(n+m,n)) * HC_R(i, max(n-m,n)) + ... +% (1-1/tau) * c(m,i,n-1), +% +% aL(m,i,n) = (1/tau) * (HC_L(i, max(n+m,n)))^2 + ... +% (1-1/tau) * aL(m,i,n-1), +% +% aR(m,i,n) = (1/tau) * (HC_R(i, max(n+m,n)))^2 + ... +% (1-1/tau) * aR(m,i,n-1), +% +% i is the frequency index, m is the lag index, and n is the sample +% index. The running (non-normalised) cross-correlation is calculated is +% simply c(m,i,n). +% +% The interaural coherence is +% +% IC(i,n) = max(C(m,i,n)) % (i.e. over m) +% +% The cross-correlogram is calculated as the sum of cross- correlations +% in a given frame: +% +% CCG(m,i,j) = sum(C(m,i,J),3) +% +% where +% +% J = (j-1) * frame_length + 1 : j * frame_length +% +% References +% +% [1] C. Faller and J. Merimaa, "Source localization in complex listening +% situations: Selection of binaural cues based on interaural +% coherence", The Journal of the Acoustical Society of America, vol. +% 116, pp.3075-3089, Nov. 2004. +% +% Further Reading +% +% C. Hummersone, R. Mason, and T. Brookes, "A comparison of computational +% precedence models for source separation in reverberant +% environments", The Journal of the Audio Engineering Society, vol. +% 61(7/8), pp.508-520, July 2013. + +% Copyright 2016 University of Surrey. + + assert(nargin>=3, 'iosr:chXcorr:nargin', 'Number of input arguments must be greater than or equal to three.') + + if isparameter(varargin,'inhib_mode') && ~isparameter(varargin,'inhib') + warning('iosr:instIld:inhibMode','''inhib_mode'' specified, but no inhibition array ''inhib''.'); + end + + % Check source file is compiled + iosr.general.checkMexCompiled('-largeArrayDims',fullfile(fileparts(mfilename('fullpath')),'chXcorr_c.c')) + + options = struct(... + 'frame_length',round(0.01*fs),... + 'noverlap',1,... + 'maxlag',round(0.001*fs),... + 'tau',round(0.01*fs),... + 'inhib',[],... + 'ic_t',0,... + 'norm_flag',0,... + 'inhib_mode','subtract'); + + % read parameter/value inputs + if nargin > 3 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:chXcorr:nameValuePair','CHXCORR needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:chXcorr:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % assign options to variables + frame_length = options.frame_length; + noverlap = options.noverlap; + maxlag = options.maxlag; + tau = options.tau; + inhib_mode = options.inhib_mode; + norm_flag = options.norm_flag; + ic_t = options.ic_t; + inhib = options.inhib; + + % check inputs + assert(all(size(hc_L)==size(hc_R)), 'iosr:chXcorr:invalidInput', '''hc_L'' and ''hc_R'' must be the same size') + assert(round(frame_length)==frame_length && isscalar(frame_length) && frame_length>0, 'iosr:chXcorr:invalidFrame', ... + '''frame_length'' must be an integer greater than zero') + assert(round(noverlap)==noverlap && isscalar(noverlap) && noverlap>0, 'iosr:chXcorr:invalidNoverlap', ... + '''noverlap'' must be an integer greater than zero') + assert(round(maxlag)==maxlag && isscalar(maxlag) && maxlag>0, 'iosr:chXcorr:invalidMaxlag', ... + '''maxlag'' must be an integer greater than zero') + assert(isscalar(tau) && tau>=1, 'iosr:chXcorr:invalidTau', '''tau'' must be a scalar greater than or equal to one') + assert(isscalar(norm_flag), 'iosr:chXcorr:invalidNorm', '''norm_flag'' must be a scalar') + assert(isscalar(ic_t) && ic_t>=0 && ic_t<=1, 'iosr:chXcorr:invalidIct', '''ic_t'' must be a scalar in the range [0,1]') + assert(ischar(inhib_mode), 'iosr:chXcorr:invalidInhibMode', '''inhib_mode'' must be a char array (string)') + + % Calculate frame count + frame_count = floor(max(size(hc_L))/(frame_length)); + frame_count = frame_count-noverlap+1; + + % Calculate number of frequency channels + numchans = min(size(hc_L)); + numsamples = max(size(hc_L)); + + % Check orientation of HC and inhib data (i.e. that frequency runs across the rows) + dims = size(hc_L); + hc_L = check_input(hc_L,2,numchans); + hc_R = check_input(hc_R,2,numchans); + + % set a flag if data has been transposed in this way + if dims(1)~=size(hc_L,1) + rot = true; + else + rot = false; + end + + % set inhibition mode ID + switch inhib_mode + case 'multiply' + inhib_mode_ID = 1; + if isempty(inhib) + inhib = ones(size(hc_L)); + end + case 'subtract' + inhib_mode_ID = 2; + if isempty(inhib) + inhib = zeros(size(hc_L)); + end + otherwise + error('iosr:chXcorr:unknownInhibMode','''inhib_mode'' must be set to ''multiply'' or ''subtract''') + end + + inhib = check_input(inhib,2,numchans); + + % Append HC and inhibition data with zeros for cross-correlation + hc_L = [hc_L; zeros(maxlag+1,numchans)]; + hc_R = [hc_R; zeros(maxlag+1,numchans)]; + inhib = [inhib; zeros(maxlag+1,numchans)]; + + assert(all(size(inhib)==size(hc_L)), 'iosr:chXcorr:invalidInhib', '''inhib'' must be a matrix the same size as ''hc_L'' or ''hc_R''') + + % Calculate cross-correlograms + [ccg,ic] = iosr.auditory.chXcorr_c(hc_L,hc_R,frame_count,frame_length,noverlap,maxlag,tau,inhib,ic_t,norm_flag,inhib_mode_ID); + + % Correct orientation of IC data, if data was transposed, and crop to remove appended zeros + ic = ic(1:numsamples,:); + if rot + ic = ic'; + end + +end + +function output = check_input(input,dim,target) +%CHECK_INPUT check input is correct orientation + + if size(input,dim)~=target + output = input'; + assert(size(output,dim)==target, 'iosr:chXcorr:invalidInputs', 'Input invalid') + else + output = input; + end + +end + +function set = isparameter(input,parameter) +%ISPARAMETER check for input parameter + + set = any(strcmpi(input(cellfun(@ischar,input)),parameter)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr2.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr2.m new file mode 100644 index 0000000000000000000000000000000000000000..82a2b21892b2d9e54f3d8f06afac91126e7e6a3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr2.m @@ -0,0 +1,128 @@ +function [ccg,ic] = chXcorr2(hc_L,hc_R,fs,varargin) +%CHXCORR2 Calculate cross-correlograms with a range of options. +% +% CCG = IOSR.AUDITORY.CHXCORR2(HC_L,HC_R,FS) cross-correlates the input +% 2-D matrices HC_L and HC_R over 10ms frame with a maximum lag of 1ms. +% It is assumed that the number of frequency channels is min(size(HC_L)) +% and hence HC_L and HC_R can be in either orientation. The +% cross-correlograms consist of cross-correlations for every frame and +% frequency channel. CCG has dimensions [lag,frequency,frame]. The +% function calculates the traditional cross-correlation in each frame. +% The number of frames FRAME_COUNT is calculated thus: +% +% FRAME_COUNT = FIX((MAX(SIZE(HC_L)))/FRAME_LENGTH); +% +% CCG = IOSR.AUDITORY.CHXCORR2(HC_L,HC_R,FS,'PARAMETER',VALUE) allows a +% number of options to be specified. The options are: +% +% ({} indicates the default value) +% +% 'frame_length' : {round(0.01*fs)} | scalar +% The length of frames (in samples) used for calculating +% cross-correlations. +% 'hop' : {[]} | scalar +% The hop size (in samples). By default the hop size is equal to the +% frame length (HOP is specified as an empty array). The hop size +% determines the number of frames as +% FIX((MAX(SIZE(HC_L))-(FRAME_LENGTH-HOP))/HOP); +% 'maxlag' : {round(0.001*fs)} | scalar +% The maximum lag of the cross-correlation (in samples). +% 'norm_flag' : {0} | scalar +% Specifies whether the cross-correlograms are calculated using +% normalised cross-correlations. A non-zero value indicates that +% normalised cross-correlations are used. +% +% [CCG,IC] = IOSR.AUDITORY.CHXCORR2(...) returns the calculated IC for +% each frame to the matrix IC. + +% Copyright 2016 University of Surrey. + + assert(nargin>=3, 'iosr:chXcorr2:nargin', 'Number of input arguments must be greater than or equal to three.') + + % Check source file is compiled + iosr.general.checkMexCompiled('-largeArrayDims',fullfile(fileparts(mfilename('fullpath')),'chXcorr2_c.c')) + + options = struct(... + 'frame_length',round(0.01*fs),... + 'maxlag',round(0.001*fs),... + 'norm_flag',0,... + 'hop',[]); + + % read parameter/value inputs + if nargin > 3 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:chXcorr2:nameValuePair','CHXCORR2 needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:chXcorr2:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % assign options to variables + frame_length = options.frame_length; + maxlag = options.maxlag; + norm_flag = options.norm_flag; + if isempty(options.hop) + hop = frame_length; + else + hop = options.hop; + end + + % check inputs + assert(all(size(hc_L)==size(hc_R)), 'iosr:chXcorr2:invalidInput', '''hc_L'' and ''hc_R'' must be the same size') + assert(round(frame_length)==frame_length && isscalar(frame_length) && frame_length>0, ... + 'iosr:chXcorr2:invalidFrame', '''frame_length'' must be an integer greater than zero') + assert(round(maxlag)==maxlag && isscalar(maxlag) && maxlag>0, 'iosr:chXcorr2:invalidMaxlag', ... + '''maxlag'' must be an integer greater than zero') + assert(isscalar(norm_flag), 'iosr:chXcorr2:invalidNorm', '''norm_flag'' must be a scalar') + + % Calculate frame count + frame_count = fix((max(size(hc_L))-(frame_length-hop))/hop); + + % Calculate number of frequency channels + numchans = min(size(hc_L)); + + % Check orientation of HC and inhib data (i.e. that frequency runs across the rows) + dims = size(hc_L); + hc_L = check_input(hc_L,2,numchans); + hc_R = check_input(hc_R,2,numchans); + + % set a flag if data has been transposed in this way + if dims(1)~=size(hc_L,1) + rot = true; + else + rot = false; + end + + % Calculate cross-correlograms + [ccg,ic] = iosr.auditory.chXcorr2_c(hc_L,hc_R,frame_count,frame_length,maxlag,hop,norm_flag); + + % Correct orientation of IC data, if data was transposed, and crop to remove appended zeros + if rot + ic = ic'; + end + +end + +function output = check_input(input,dim,target) +%CHECK_INPUT check input is correct orientation + + if size(input,dim)~=target + output = input'; + assert(size(output,dim)==target, 'iosr:chXcorr2:invalidInput', 'Input invalid') + else + output = input; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr2_c.c b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr2_c.c new file mode 100644 index 0000000000000000000000000000000000000000..ab6d63e7d39c827caad0dcc632173a098a8c59ff --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr2_c.c @@ -0,0 +1,197 @@ +/* + * Calculate cross-correlograms with a range of options. + * Called from chXcorr2.m. + * + * Copyright 2016 University of Surrey. + * + */ + +#include "math.h" +#include "mex.h" +#include "matrix.h" + +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +/* structure for cross-correlation info */ +struct xcorr +{ + int maxlag; + double ic; + double *c; + double *nc; + double *aL; + double *aR; +}; + +/* cross-correlation functions */ +void xcorr(double L[], double R[], int frame_length, int numsamples, struct xcorr * data); +void initXcorr(unsigned int maxlag, unsigned int length, struct xcorr * data); +void freeXcorr(struct xcorr * data); + +/* main function */ +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + /* ====================== DECLARATIONS ====================== */ + + double + *hc_L = mxGetPr(prhs[0]), /* input left signal */ + *hc_R = mxGetPr(prhs[1]), /* input right signal */ + *cout; /* output */ + + int + frame_count = *mxGetPr(prhs[2]), /* Input number of frames in input */ + frame_length = *mxGetPr(prhs[3]), /* Frame length */ + maxlag = *mxGetPr(prhs[4]), /* Maximum lag for cross-correlation */ + hop = *mxGetPr(prhs[5]), /* hop size */ + norm_flag = *mxGetPr(prhs[6]), /* normalisation flag */ + lengthCCG = (2*maxlag)+1; /* Cross-correlation length */ + + mwSize + numsamples = mxGetM(prhs[0]), /* Number of samples in HC data */ + numchans = mxGetN(prhs[0]); /* Number of frequency channels in input HC data */ + + /* Indices */ + mwIndex + m, /* lag index */ + i, /* Frequency channel index */ + j, /* Frame index */ + sample, /* sample index */ + index_ccg, /* Index to CCG */ + index_ic; /* index into interaural coherence */ + + /* cross-correlation data */ + struct xcorr ccdata; + initXcorr(maxlag, lengthCCG, &ccdata); + + /* choose output according to normalisation */ + if (norm_flag == 0) { + cout = ccdata.c; + } + else { + cout = ccdata.nc; + } + + /* ====================== OUTPUTS ====================== */ + + mwSize ccg_dims[3] = {(mwSize)lengthCCG, numchans, (mwSize)frame_count}; /* CCG dimensions */ + plhs[0] = mxCreateNumericArray(3,ccg_dims,mxDOUBLE_CLASS,mxREAL); + plhs[1] = mxCreateDoubleMatrix(frame_count,numchans,mxREAL); + double *ccg_out = mxGetPr(plhs[0]), + *ic_out = mxGetPr(plhs[1]); + + /* ====================== CROSS-CORRELATE ====================== */ + for ( j = 0; j < frame_count; j++ ) { + for ( i = 0; i < numchans; i++ ) { + /* indices */ + sample = (i*(mwIndex)numsamples)+(j*(mwIndex)hop); + index_ccg = (i*lengthCCG)+(j*lengthCCG*numchans); + index_ic = (i*(mwIndex)frame_count)+j; + /* cross-correlate */ + xcorr(hc_L+sample, hc_R+sample, frame_length, numsamples, &ccdata); + /* outputs */ + ic_out[index_ic] = ccdata.ic; + for ( m = 0; m < lengthCCG; m++ ) { + ccg_out[index_ccg+m] = cout[m]; + } + } /* end frequency loop */ + } /* end frame loop */ + /* Destroy arrays */ + freeXcorr(&ccdata); + return; +} + +void xcorr(double L[], double R[], int frame_length, int numsamples, struct xcorr * data) +{ + + int m, /* lag index */ + n, /* sample index */ + maxlag = data->maxlag; /* maximum cross-correlation lag */ + double + Rshift, /* shifted right signal */ + mL = 0.0, /* mean of left */ + mR = 0.0, /* mean of right */ + denom, /* denominator */ + *c = data->c, /* cross-correlation */ + *nc = data->nc, /* normalised cross-correlation */ + *aL = data->aL, /* left variance */ + *aR = data->aR, /* right variance */ + *ic = &(data->ic); /* interaural coherence */ + + /* reset arrays to 0 */ + for (m = 0; m < 2*maxlag+1; m++) { + c[m] = 0.0; + nc[m] = 0.0; + aL[m] = 0.0; + aR[m] = 0.0; + } + + /* calculate mean of time series */ + for (n = 0; n < frame_length; n++) { + mL += L[n]/frame_length; + mR += R[n]/frame_length; + } + + /* calculate cross-correlations of time series */ + for (m = -maxlag; m <= maxlag; m++) { + for (n = 0; n < frame_length; n++) { + /* do not wrap, but set out-of-bounds to zero */ + if (((n-m) < 0) || ((n-m) > frame_length) || ((n-m) > numsamples)) { + Rshift = 0.0; + } + else { + Rshift = R[n-m]; + } + /* cross-correlate */ + c[m+maxlag] += (L[n]-mL) * (Rshift-mR); /* cross-correlation */ + aL[m+maxlag] += pow(L[n]-mL,2.0); /* variance of left */ + aR[m+maxlag] += pow(Rshift-mR,2.0); /* variance of right */ + } + } + + /* normalise the cross-correlation */ + data->ic = 0.0; /* reset to 0 */ + for (m = 0; m < 2*maxlag+1; m++) { + denom = sqrt(aL[m])*sqrt(aR[m]); /* denominator */ + if (denom > 0.0) { + nc[m] = c[m]/denom; + } + else { /* prevent divide by zero */ + nc[m] = 0.0; + } + /* calculate coherence */ + *ic = max(*ic,nc[m]); + } + + return; + +} + +void initXcorr(unsigned int maxlag, unsigned int length, struct xcorr * data) +{ + /* initialise and allocate data */ + data->maxlag = maxlag; + data->ic = 0.0; + data->c = calloc(length,sizeof(double)); + data->nc = calloc(length,sizeof(double)); + data->aL = calloc(length,sizeof(double)); + data->aR = calloc(length,sizeof(double)); + if (length != 0 && (!data->c || !data->nc || !data->aL || !data->aR)) { + freeXcorr(data); + } +} + +void freeXcorr(struct xcorr * data) +{ + /* free memory */ + if (data->c) + free(data->c); + if (data->nc) + free(data->nc); + if (data->aL) + free(data->aL); + if (data->aR) + free(data->aR); +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr_c.c b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr_c.c new file mode 100644 index 0000000000000000000000000000000000000000..67acf5912356ec84c2d6990051b7d07b99a5977d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/chXcorr_c.c @@ -0,0 +1,205 @@ +/* + * Calculate cross-correlograms with a wide range of options. + * Called from chXcorr.m. + * + * Copyright 2016 University of Surrey. + * + */ + +#include "math.h" +#include "mex.h" +#include "matrix.h" + +#define INHIB_MULTIPLY 1 +#define INHIB_SUBTRACT 2 + +#define MAX(A,B) ((A)>(B) ? (A) : (B)) + +#define A_TEMP_ARRAY mxCreateDoubleMatrix((mwSize)lengthCCG,numchans,mxREAL) +#define CCG_TEMP_ARRAY mxCreateNumericArray((mwSize)3,ccg_r_dims,mxDOUBLE_CLASS,mxREAL) + +double xcorr(double L, double R, double prev, double tc) { + return ((1.0/tc)*L*R) + ((1.0-(1.0/tc))*prev); +} + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + /* ====================== DECLARATIONS ====================== */ + + double *hc_L = mxGetPr(prhs[0]), /* input left signal */ + *hc_R = mxGetPr(prhs[1]); /* input right signal */ + + int frameCount = *mxGetPr(prhs[2]), /* Input number of frames in input */ + frame_length = *mxGetPr(prhs[3]), /* Frame length */ + noverlap = *mxGetPr(prhs[4]), /* Number of frames to overlap in CCG calculations */ + maxlag = *mxGetPr(prhs[5]); /* Maximum lag for cross-correlation */ + + double tau = *mxGetPr(prhs[6]), /* Time constant for cross-correlation calculation */ + *inhib = mxGetPr(prhs[7]), /* Inhibition data */ + ic_t = *mxGetPr(prhs[8]); /* Interaural coherence threshold */ + + int norm_flag = *mxGetPr(prhs[9]), /* Normalisation flag: 0 = no normalisation, any other value indicates normalisation */ + inhib_mode_ID = *mxGetPr(prhs[10]); /* Inhibition mode: 1 = multiplication, 2 = subtraction */ + + mwSize numsamples = mxGetM(prhs[0]), /* Number of samples in HC data */ + numchans = mxGetN(prhs[0]); /* Number of frequency channels in input HC data */ + + /* The IC for the cross-correlation at the current sample */ + double ic; + + int ic_count = 0, /* Counts number of samples over IC_T */ + lengthCCG = (2*maxlag)+1, /* Cross-correlation length */ + lookahead = 0; /* Number of frames to look ahead for CCG calculation */ + + /* Indices */ + mwIndex i, /* Frequency channel index */ + j, /* Frame index */ + n, /* Sample index */ + m, /* Lag index */ + sample, /* sample index */ + ic_sample, /* IC sample index */ + index_ccg_r, /* Running cross-correlation index */ + index_ccg_r_ahead, /* Running cross-correlation index for look ahead frame */ + index_a, /* Index to auto- and cross-correlations */ + index_ccg, /* Index to CCG */ + leftn, /* Left index for calculating cross-correlations */ + rightn; /* Right index for calculating cross-correlations */ + + /* Dimensions */ + mwSize ccg_dims[3] = {(mwSize)lengthCCG, numchans, (mwSize)frameCount}, /* CCG dimensions */ + ccg_r_dims[3] = {(mwSize)lengthCCG, (mwSize)frame_length*noverlap, numchans}; /* Running cross-correlation dimensions */ + + /* ====================== TEMP ARRAYS ====================== */ + + /* Running auto- and cross-correlations for previous sample */ + mxArray *a_LL_prev_mx,*a_RR_prev_mx,*a_LR_prev_mx; + a_LL_prev_mx = A_TEMP_ARRAY; + a_RR_prev_mx = A_TEMP_ARRAY; + a_LR_prev_mx = A_TEMP_ARRAY; + double *a_LL_prev = mxGetPr(a_LL_prev_mx), + *a_RR_prev = mxGetPr(a_RR_prev_mx), + *a_LR_prev = mxGetPr(a_LR_prev_mx); + + /* Running auto- and cross-correlations */ + mxArray *a_LL_mx,*a_RR_mx,*a_LR_mx; + a_LL_mx = A_TEMP_ARRAY; + a_RR_mx = A_TEMP_ARRAY; + a_LR_mx = A_TEMP_ARRAY; + double *a_LL = mxGetPr(a_LL_mx), + *a_RR = mxGetPr(a_RR_mx), + *a_LR = mxGetPr(a_LR_mx); + + /* Cross-correlations */ + mxArray *ccg_norm_mx, *ccg_r_mx, *ccg_ic_mx; + ccg_norm_mx = CCG_TEMP_ARRAY; + ccg_r_mx = CCG_TEMP_ARRAY; + ccg_ic_mx = mxCreateDoubleMatrix((mwSize)lengthCCG,(mwSize)1,mxREAL); + double ccg_ic_temp, + *ccg_norm = mxGetPr(ccg_norm_mx), + *ccg_r = mxGetPr(ccg_r_mx), + *ccg_ic = mxGetPr(ccg_ic_mx); + + /* ====================== OUTPUTS ====================== */ + + plhs[0] = mxCreateNumericArray(3,ccg_dims,mxDOUBLE_CLASS,mxREAL); + plhs[1] = mxCreateDoubleMatrix(numsamples,numchans,mxREAL); + double *ccg_out = mxGetPr(plhs[0]), + *ic_out = mxGetPr(plhs[1]); + + /* ====================== CROSS-CORRELATE ====================== */ + for ( j = 0; j < frameCount; j++ ) { + for ( i = 0; i < numchans; i++ ) { + index_ccg = (i*lengthCCG)+(j*lengthCCG*numchans); + sample = (i*(mwIndex)numsamples)+((j+lookahead)*(mwIndex)frame_length); + ic_sample = (i*(mwIndex)numsamples)+(j*(mwIndex)frame_length); + for ( m = 0; m < lengthCCG; m++ ) {/* reset ccg for T-F unit */ + ccg_ic[m] = 0.0; + } + /* Calculate raw cross-correlations */ + for ( n = 0; n < frame_length*(noverlap-lookahead); n++ ) { + index_a = (i*lengthCCG); + index_ccg_r = ((n+(lookahead*frame_length))+i*(noverlap*frame_length))*lengthCCG; + ic = 0.0; /* reset the IC value for the sample */ + for ( m = 0; m < lengthCCG; m++ ) { /* calculate cross-correlations */ + leftn = sample+n+( (m>maxlag) ? (m-maxlag) : (0) ); + rightn = sample+n+( (m<maxlag) ? (maxlag-m) : (0) ); + a_LR[index_a+m] = xcorr(hc_L[leftn],hc_R[rightn],a_LR_prev[index_a+m],tau); + a_LL[index_a+m] = xcorr(hc_L[leftn],hc_L[leftn],a_LL_prev[index_a+m],tau); + a_RR[index_a+m] = xcorr(hc_R[rightn],hc_R[rightn],a_RR_prev[index_a+m],tau); + ccg_norm[index_ccg_r+m] = a_LR[index_a+m]/sqrt(a_LL[index_a+m]*a_RR[index_a+m]); + if ( (a_LL[index_a+m]*a_RR[index_a+m])==0.0 ) { /* prevent divide by zero */ + ccg_norm[index_ccg_r+m] = 0.0; + } + ic = MAX(ic,ccg_norm[index_ccg_r+m]); /* calculate IC for sample (as max) */ + if ( norm_flag == 0 ) { + /* Un-normalised */ + ccg_r[index_ccg_r+m] = a_LR[index_a+m]; + } + else { + /* Normalised */ + ccg_r[index_ccg_r+m] = ccg_norm[index_ccg_r+m]; + } + /* Set cross-correlations for what will become the previous sample */ + a_LR_prev[index_a+m] = a_LR[index_a+m]; + a_LL_prev[index_a+m] = a_LL[index_a+m]; + a_RR_prev[index_a+m] = a_RR[index_a+m]; + } + ic_out[sample+n] = ic; /* Write IC to output */ + } + ic_count = 0; /* reset the count of samples with IC values over the IC threshold */ + /* Integrate cross-correlations */ + for ( n = 0; n < frame_length*noverlap; n++ ) { + index_ccg_r = (n+i*(frame_length*noverlap))*lengthCCG; + if ( ic_out[ic_sample+n] >= ic_t ) { /* check if IC exceeds IC threshold */ + ic_count++; /* count the number of samples that exceed the IC threshold */ + for ( m = 0; m < lengthCCG; m++ ) { /* inhibit (multiplication) */ + switch (inhib_mode_ID) { + case INHIB_MULTIPLY: + ccg_ic[m] += ccg_r[index_ccg_r+m]*inhib[sample+n]; + break; + case INHIB_SUBTRACT: + ccg_ic_temp = ccg_r[index_ccg_r+m]-((1.0/tau)*inhib[sample+n]); + ccg_ic[m] += MAX(ccg_ic_temp,0.0); + break; + default: + mexErrMsgTxt("Unknown inhib_mode_ID"); + } + } + } + else { + ic_out[ic_sample+n] = 0; + } + } + if ( ic_count == 0 ) { /* write zeros to output if no samples in frame have high enough IC */ + for ( m = 0; m < lengthCCG; m++ ) { + ccg_out[index_ccg+m] = 0.0; + } + } + else { /* average CCGs with high enough IC */ + for ( m = 0; m < lengthCCG; m++ ) { + ccg_out[index_ccg+m] = ccg_ic[m]/(double)ic_count; /* Write CCG to output */ + } + } + /* move ccg_r's backwards to append for subsequent frames */ + for ( n = 0; n < frame_length*(noverlap-1); n++ ) { + index_ccg_r = (n+i*(frame_length*noverlap))*lengthCCG; + index_ccg_r_ahead = ((n+frame_length)+i*(frame_length*noverlap))*lengthCCG; + for ( m = 0; m < lengthCCG; m++ ) { + ccg_r[index_ccg_r+m] = ccg_r[index_ccg_r_ahead+m]; + } + } + } /* end frequency loop */ + lookahead = noverlap-1; /* Set value */ + } /* end frame loop */ + /* Destroy mx arrays */ + mxDestroyArray(ccg_norm_mx); + mxDestroyArray(ccg_r_mx); + mxDestroyArray(ccg_ic_mx); + mxDestroyArray(a_LL_mx); + mxDestroyArray(a_RR_mx); + mxDestroyArray(a_LR_mx); + mxDestroyArray(a_LL_prev_mx); + mxDestroyArray(a_RR_prev_mx); + mxDestroyArray(a_LR_prev_mx); + return; +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/createWindow.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/createWindow.m new file mode 100644 index 0000000000000000000000000000000000000000..33ba7ae585fd58550669ea0e6c0e4e012e2b8ee2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/createWindow.m @@ -0,0 +1,186 @@ +function OutWin = createWindow(varargin) +% Create a Hann or exp. window with specified onsets/offsets +% +% OutWin = iosr.auditory.createWindow(WinLen, Type, Duration) +% +% Other (non-symmetric) uses include: +% +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Hann, ... +% OnDuration, ... +% Hann, ... +% OffDuration,) +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Hann, ... +% OnDuration, ... +% Exp, ... +% OffDuration, ... +% OffSlope) +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Exp, ... +% OnDuration, ... +% OnSlope, ... +% Hann, ... +% OffDuration) +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Exp, ... +% OnDuration, ... +% OnSlope, ... +% Exp, ... +% OffDuration, ... +% OffSlope) +% +% OutWin = iosr.auditory.createWindow(type, samples) +% OutWin = iosr.auditory.createWindow(Ontype, Onsamples, ... +% Offtype, Offsamples) +% +% In the first mode of operation, the onset and offset are assumed to be +% identical (symmetric window). In other modes, the OnRamp and OffRamp +% durations (and slopes if necessary) are specified independently +% +% OutWin: the created window +% +% WinLen: the total duration (in samples) of the desired window +% +% Type (inc. Ontype and Offtype): +% +% - 'Hann': a raised cosine ramp, following value should always be the +% Duration of the ramp +% +% - 'Exp': an exponential ramp, following value should be always be the +% Duration of the ramp, and then the Slope. e.g Slope > 3 very shallow, +% slope < 0.1 very steep +% +% Duration: number of samples over which the OnRamp and OffRamp are applied +% +% Slope: the steepness of the exponential ramp +% +% Example case: 100 samples onset Hann, followed by 50 unramped samples +% (i.e. value = 1), followed by 500 samples of shallow exponential offset +% ramp +% +% OutWin = iosr.auditory.createWindow(650, 'Hann', 100, 'Exp', 500, 3) + +% Copyright 2016 University of Surrey. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Begin Create Window +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% test input types +assert(isnumeric(varargin{1}),['1st input should be window length' ... +'specified in samples']); +assert(size(varargin, 2)>2,'not enough input arguments'); +assert(size(varargin, 2)<8,'too many input arguments'); + +%% extract inputs +nInputs = (size(varargin, 2)); +WinLen = varargin{1}; +Slope = [0 0]; +switch nInputs + + case 3 % Hann or Rec symmetric window + assert(~strcmp(varargin{2},('Exp')),'Must specify slope of exponential'); + assert(strcmp(varargin{2},('Hann')) || strcmp(varargin{2},('Rec')),'Input type not specified'); + RampOn = varargin{2}; + RampOff = varargin{2}; + RampOnDur = varargin{3}; + RampOffDur = varargin{3}; + case 4 % Exp symmetric window + assert(strcmp(varargin{2},('Exp')),'wrong number of input arguments or ramp type'); + assert(varargin{4}~=0,'exponential slope may not be 0'); + RampOn = 'Exp'; + RampOff = 'Exp'; + RampOnDur = varargin{3}; + RampOffDur = varargin{3}; + Slope(1) = varargin{4}; + case 5 % Hann or Rec ramp on and ramp off + assert(strcmp(varargin{2},('Hann')) || strcmp(varargin{2},('Rec')),'Input type not specified'); + assert(strcmp(varargin{4},('Hann')) || strcmp(varargin{4},('Rec')),'Input type not specified'); + RampOn = varargin{2}; + RampOff = varargin{4}; + RampOnDur = varargin{3}; + RampOffDur = varargin{5}; + case 6 % (Hann or Rec) + Exp, or Exp + (Hann or Rec) + if (strcmp(varargin{2},'Hann')||strcmp(varargin{2},'Rec')) + RampOn = varargin{2}; + RampOnDur = varargin{3}; + RampOff = 'Exp'; + RampOffDur = varargin{5}; + Slope(2) = varargin{6}; + elseif strcmp(varargin{2},'Exp') + RampOn = 'Exp'; + RampOnDur = varargin{3}; + assert(isnumeric(varargin{4}),'exponential slope should be specified as arg 4'); + assert(varargin{4}~=0,'exponential slope may not be 0'); + Slope(1) = varargin{4}; + RampOff = varargin{5}; + RampOffDur = varargin{6}; + else + error('incorrect input arguments'); + end +case 7 % Ramp on = Exp, Ramp off = Exp + assert(strcmp(varargin{2},('Exp')) && strcmp(varargin{2},('Exp')),'both ramps should be Exp for 7 input arguments'); + RampOn = 'Exp'; + RampOff = 'Exp'; + RampOnDur = varargin{3}; + Slope(1) = varargin{4}; + RampOffDur = varargin{6}; + Slope(2) = varargin{7}; + otherwise + error('incorrect number of inputs'); +end +assert(WinLen>=((RampOnDur)+(RampOffDur)),'ramp lengths greater than signal duration!'); + +%% Test Hann gives correct answer for dummy example +assert( 0.01 > ( max(abs( AppWin(100,'Hann',10,'Hann',10) - ... + [ 0; 0.0245; 0.0955; 0.2061; 0.3455; 0.5000; ... + 0.6545; 0.7939; 0.9045; 0.9755; ... + ones(80,1); ... + 0.9755; 0.9045; 0.7939; 0.6545; 0.5000; ... + 0.3455; 0.2061; 0.0955; 0.0245; 0 ]))), ... + 'Hann not functioning corectly'); + +%% Do Work +OutWin = AppWin(WinLen,RampOn,RampOnDur,RampOff,RampOffDur,Slope); + +end + +% ---------------------------------------------------------- +% DO AppWin +% ---------------------------------------------------------- +function OutWin = AppWin(WinLen,RampOn,RampOnDur,RampOff,RampOffDur,Slope) + +% generate rectangular window +OutWin = ones(WinLen,1); + +%% Create the ramp on +switch RampOn + case 'Hann' + OutWin(1:RampOnDur) = (1-cos(pi/RampOnDur*[0:RampOnDur-1])) / 2; + + case 'Exp' + OutWin(1:RampOnDur) = exp(([1:RampOnDur]./(Slope(1)*RampOnDur))-(1/Slope(1))); + + case 'Rec' + + otherwise + error('ramp on unspecified'); +end + +%% Create the ramp off +switch RampOff + case 'Hann' + OutWin(end-RampOffDur+1:end) = (1+cos(pi/RampOffDur*[1:RampOffDur]))/2; + + case 'Exp' + OutWin(end-RampOffDur+1:end) = exp((fliplr([1:RampOffDur])./(Slope(2)*RampOffDur))-(1/Slope(2))); + + case 'Rec' + + otherwise + error('ramp off unspecified'); +end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/dupWeight.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/dupWeight.m new file mode 100644 index 0000000000000000000000000000000000000000..ee2ebb54c90258704406119cc3501a4dd6bae906 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/dupWeight.m @@ -0,0 +1,67 @@ +function [w_itd,w_ild] = dupWeight(f) +%DUPWEIGHT Calculate duplex weighting coefficients for ITD and ILD +% +% [W_ITD,W_ILD] = IOSR.AUDITORY.DUPWEIGHT(F) returns the weighting +% coefficients for ITD W_ITD and ILD W_ILD for frequency F (Hz). +% +% The function is derived from Ben Supper's thesis "An onset-guided +% spatial analyser for binaural audio", with some necessary +% modifications. Specifically, his work accounts for the ITD dominance +% condition. This function does not, as this cannot be derived from the +% work, since the work assumes an upper frequency limit of 13750 Hz +% (which cannot be assumed in this function). The quadratic ramp in ITD +% weighting is approximated linearly here. +% +% The input f may be an array of any size. The outputs will be the same +% size as f, with coefficients calculated for each element. +% +% See also IOSR.AUDITORY.LOUDWEIGHT. + +% Copyright 2016 University of Surrey. + + %% Check input + + assert(all(f(:)>=0), 'iosr:functionalBoxPlot:invalidF', 'f should be greater than or equal to zero!') + + if any(f(:)>20000) + warning('iosr:dupWeight:frequencyRange','Humans cannot generally hear above 20 kHz. Weighting coefficients will be set to zero.') + end + + %% Calculate original weights using Ben's numbers + + % Frequency scale in Ben's thesis + freq_scale = [60 150 250 350 455 570 700 845 1000 1175 ... + 1375 1600 1860 2160 2510 2925 3425 4050 4850 5850 ... + 7050 8600 10750 13750]; + + % Corresponding bin numbers + b = 1:24; + + % frequency ranges (indices) + low = b<=8; % below cross-over region + mid = b>8 & b<14; % cross-over region + high = b>=14; % above cross-over region + + % pre-allocate outputs + w_itd_orig = zeros(size(freq_scale)); + w_ild_orig = zeros(size(freq_scale)); + + % Do maths + w_itd_orig(low) = 1.597-(0.047*b(low)); + w_itd_orig(mid) = (0.0102.*(b(mid).^2))-(0.437.*b(mid))+4.06; + w_itd_orig(high) = 0.11; + % + w_ild_orig(low) = 0.2; + w_ild_orig(mid) = (0.152.*b(mid))-1.016; + w_ild_orig(high) = 0.96; + + %% Calculate weights for input frequencies + + % ...via interpolation + w_itd = interp1(freq_scale,w_itd_orig,f,'pchip','extrap'); + w_ild = interp1(freq_scale,w_ild_orig,f,'pchip','extrap'); + + w_itd(f>20000) = 0; + w_ild(f>20000) = 0; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/erbRate2hz.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/erbRate2hz.m new file mode 100644 index 0000000000000000000000000000000000000000..5fca853d1c28eb0d1e122e995cebc5a4d06049a1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/erbRate2hz.m @@ -0,0 +1,13 @@ +function y=erbRate2hz(x) +%ERBRATE2HZ Convert ERB rate to Hz. +% +% Y = IOSR.AUDITORY.ERBRATE2HZ(X) converts the ERB number X to the +% eqivalent frequency Y (in Hz). +% +% See also IOSR.AUDITORY.HZ2ERBRATE. + +% Copyright 2016 University of Surrey. + + y=(10.^(x/21.4)-1)/4.37e-3; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/freqMulti.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/freqMulti.m new file mode 100644 index 0000000000000000000000000000000000000000..2f0312ebc44c91361cadcec790e3bf354c1b2a87 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/freqMulti.m @@ -0,0 +1,24 @@ +function PI = freqMulti(f) +%FREQMULTI Calculate frequency coefficient for ITD-azimuth warping +% +% PI = IOSR.AUDITORY.FREQMULTI(F) calculates the coefficient PI for +% frequency F for use in converting between ITD and azimuth in Kuhn's +% model [1]. +% +% References +% +% [1] Kuhn, G.F. (1977), Model for the interaural time differences in the +% azimuthal plane, The Journal of the Acoustical Society of America +% 62, 1, 157-167. +% +% See also IOSR.AUDITORY.AZIMUTH2ITD, IOSR.AUDITORY.ITD2AZIMUTH. + +% Copyright 2016 University of Surrey. + + PI = zeros(size(f)); + PI(f<=500) = 3; + PI(f>=3000) = 2; + IX = f>500 & f<3000; + PI(IX) = 2.5+0.5.*cos(pi.*((log2((sqrt(6).*f(IX))./1250))./(log2(6)))); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/gammatoneFast.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/gammatoneFast.m new file mode 100644 index 0000000000000000000000000000000000000000..452a977c0418f98da1291424e63e6ac4251e7949 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/gammatoneFast.m @@ -0,0 +1,107 @@ +function [bm,env,delay] = gammatoneFast(x,cfs,fs,align) +%GAMMATONEFAST Produce an array of responses from gammatone filters via FFT +% +% BM = IOSR.AUDITORY.GAMMATONEFAST(X,CFS,FS) passes the vector X through +% a bank of fourth-order gammatone filters, with centre frequencies +% specified by CFS. The function returns a matrix, with each row/column +% corresponding to a filter output with a centre frequency determined by +% the corresponding element in CFS. The orientation of the output is +% determined by the orientation of the input: if X is a row vector then +% the output will contain one row for each filter output, and vice versa. +% +% Centre frequencies may be any value below the Nyquist rate (determined +% by the sampling frequency fs). Typically centre frequencies are equally +% spaced on the ERB-rate scale and may be calculated thus: +% +% CFS = iosr.auditory.makeErbCFs(LOW_CF,HIGH_CF,NUMCHANS) +% +% where LOW_CF is the lowest frequency in the bank, HIGH_CF is the +% highest, and NUMCHANS is the numbers of filters in the bank. +% +% BM = IOSR.AUDITORY.GAMMATONEFAST(...,ALIGN) allows phase alignment to +% be applied. With ALIGN=false, no alignment is applied (default). With +% ALIGN=true, fine structure and envelope alignment is applied so that +% the impulse response peaks occurs at t=0. +% +% [BM,ENV] = IOSR.AUDITORY.GAMMATONEFAST(...) returns the instantaneous +% envelopes ENV for each filter. +% +% [BM,ENV,DELAY] = IOSR.AUDITORY.GAMMATONEFAST(...) returns the delay +% DELAY (in samples) removed by the phase alignment of each gammatone +% filter, i.e. DELAY(n)=0 if ALIGN=true. DELAY is a vector the same size +% as CFS. +% +% Based on code written by ZZ Jin, adapted by DLW in Jan'07 and JF +% Woodruff in Nov'08 +% +% See also IOSR.AUDITORY.MAKEERBCFS. + +% Copyright 2016 University of Surrey. + + if nargin < 3 + fs = 16000; % default sampling frequency + end + if nargin < 4 + align = false; % default phase alignment + end + + % check inputs + assert(isvector(x) & isnumeric(x), 'iosr:gammatoneFast:invalidX', 'x must be a vector') + assert(isvector(cfs) & isnumeric(cfs), 'iosr:gammatoneFast:invalidCfs', 'cfs must be a vector') + assert(isscalar(fs), 'iosr:gammatoneFast:invalidFs', 'fs must be a scalar') + assert(islogical(align) & numel(align)==1, 'iosr:gammatoneFast:invalidAlign', 'align must be logical') + + % number of frequency channels + numchans = length(cfs); + + filterOrder = 4; % filter order + gL = 2^nextpow2(0.128*fs); % gammatone filter length at least 128 ms + b = 1.019.*24.7.*(4.37.*cfs./1000+1); % rate of decay or bandwidth + + gt = zeros(gL,numchans); % Initialise IR + tc = zeros(size(cfs)); % Initialise time lead + phase = 0; + + tpt=(2*pi)/fs; + gain=((1.019.*b.*tpt).^filterOrder)./6; % based on integral of impulse + + tmp_t = (0:gL-1)/fs; + + % calculate impulse response + for i = 1:numchans + if align + tc(i) = (filterOrder-1)./(2*pi*b(i)); + phase = -2*pi*cfs(i)*tc(i); + end + gt(:,i) = gain(i)*fs^3*tmp_t.^(filterOrder-1).*exp(-2*pi*b(i)*tmp_t).*cos(2*pi*cfs(i)*tmp_t+phase); + end + + % if input is row vector, transpose to column vector + rot = false; + if size(x,1)==1 + x = x'; + rot = true; + end + + % gammatone filtering using FFTFILT + bm = fftfilt(gt,repmat(x,1,numchans)); + + % Hilbert envelope + env = abs(hilbert(bm)); + + % delay due to time lead + delay = round(tc.*fs); + + % remove time lead + for i = 1:numchans + bm(:,i) = [bm(delay(i)+1:end,i); zeros(delay(i),1)]; + env(:,i) = [env(delay(i)+1:end,i); zeros(delay(i),1)]; + end + + % transpose output if necessary + if rot + bm = bm'; + env = env'; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/hz2erbRate.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/hz2erbRate.m new file mode 100644 index 0000000000000000000000000000000000000000..5223ffa7e293e1b27526b01c183f4bfdee431c5e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/hz2erbRate.m @@ -0,0 +1,13 @@ +function y=hz2erbRate(x) +%HZ2ERBRATE Convert Hz to ERB rate +% +% Y = IOSR.AUDITORY.HZ2ERBRATE(X) converts the frequency X (in Hz) to the +% eqivalent ERB number Y. +% +% See also IOSR.AUDITORY.ERBRATE2HZ, IOSR.AUDITORY.MAKEERBCFS. + +% Copyright 2016 University of Surrey. + + y=(21.4*log10(4.37e-3*x+1)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/iso226.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/iso226.m new file mode 100644 index 0000000000000000000000000000000000000000..f028332b44578ea66e50f1debb3b203cfa963b21 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/iso226.m @@ -0,0 +1,176 @@ +function [spl, f, params] = iso226(phon,fq,sq) +%ISO226 ISO 226:2003 Normal equal-loudness-level contours +% +% [SPL,F] = IOSR.AUDITORY.ISO226(PHON) returns the sound pressure level +% (SPL) (dB) of pure tone frequencies F (Hz) at the loudness level(s) +% PHON. The values are calculated according to ISO 226:2003 using the +% reference frequencies specified in the standard. According to the +% standard, PHON is only valid at all frequencies if 20<=PHON<80 +% (although the function will return SPL values outside of this range). +% If PHON is 0, the threshold of hearing is returned. +% +% PHON may be an array of any size; SPL and F will be of size +% [1,29,M,N,P,...] where M,N,P,... are the dimensions of PHON. +% +% [SPL,F] = IOSR.AUDITORY.ISO226(PHON,FQ) returns the SPL of the pure +% tone frequencies in FQ at the specified loudness level(s). For +% non-standard frequencies, the SPL is calculated by interpolating the +% parameters used in its calculation. According to the standard, FQ is +% only valid between 20 Hz and 12.5 kHz; the function will extrapolate +% SPL values above 12.5 kHz by mirroring 20 Hz values at 20 kHz. +% +% FQ may be an array of any size; SPL and F will be of size +% [Q,R,S,...,M,N,P,...] where Q,R,S,... are the dimensions of FQ. +% +% ... = IOSR.AUDITORY.ISO226(PHON,FQ,SQ) specifies whether singleton +% dimensions will be removed from the output. With sq=false, singleton +% dimensions will be retained (default), else they will be removed. +% +% ... = IOSR.AUDITORY.ISO226(PHON,[],SQ) uses the standard reference +% frequencies for SPL calculations. +% +% [SPL,F,PARAMS] = IOSR.AUDITORY.ISO226(...) returns the reference +% parameters used to calculate the normal equal-loudness-level contours. +% PARAMAS is a structure with the following fields: +% 'f' : the reference frequencies, +% 'alpha_f' : the exponent of loudness perception, +% 'L_U' : magnitude of the linear transfer function normalized +% at 1000 Hz, and +% 'T_f' : the threshold of hearing. +% +% Example +% +% % Plot equal-loudness contours between 20 and 80 phon +% +% % Calculate SPLs +% phons = 20:10:80; +% [spl,f] = iosr.auditory.iso226(phons,[],true); +% +% % plot +% figure; semilogx(f,spl) +% set(gca,'xlim',[min(f(:)) max(f(:))]) +% legend(num2str(phons'),'location','southwest'); +% title('Equal loudness contours for different loudness levels (in phons)') +% xlabel('Frequency [Hz]') +% ylabel('SPL [dB]') +% +% See also IOSR.AUDITORY.LOUDWEIGHT. + +% Copyright 2016 University of Surrey. + + %% Check input + + if any(phon > 80) + warning('iosr:iso226:phonRange','SPL values may not be accurate for loudness levels above 80 phon.') + elseif any(phon(phon~=0) < 20) + warning('iosr:iso226:phonRange','SPL values may not be accurate for loudness levels below 20 phon.') + end + + if nargin>1 + if ~isempty(fq) + if any(fq(:) < 20 | fq(:) > 4000) && any(phon > 90) + warning('iosr:iso226:frequencyRange','ISO 226:2003 is valid for 20?4000 Hz only up to 90 phon. SPL values may be inaccurate.') + elseif any(fq(:) < 5000 | fq(:) > 12500) && any(phon > 80) + warning('iosr:iso226:frequencyRange','ISO 226:2003 is valid for 5000?12500 Hz only up to 80 phon. SPL values may be inaccurate.') + elseif any(fq(:)>12500) + warning('iosr:iso226:frequencyRange','ISO 226:2003 defines loudness levels up to 12.5 kHz. SPL values for frequencies above 12.5 kHz may be inaccurate.') + end + assert(all(fq(:)>=0), 'iosr:iso226:invalidFrequencies', 'Frequencies must be greater than or equal to 0 Hz.') + end + else + fq = []; + end + + if nargin<3 + sq = false; + else + assert(islogical(sq), 'iosr:iso226:invalidSq', 'sq must be logical.') + end + + %% References + + % reference frequencies + params.f = [20 25 31.5 40 50 63 80 100 125 160 200 250 315 400 ... + 500 630 800 1000 1250 1600 2000 2500 3150 4000 5000 ... + 6300 8000 10000 12500]; + + % exponent of loudness perception + params.alpha_f = [0.532 0.506 0.480 0.455 0.432 0.409 0.387 ... + 0.367 0.349 0.330 0.315 0.301 0.288 0.276 0.267 0.259... + 0.253 0.250 0.246 0.244 0.243 0.243 0.243 0.242 0.242... + 0.245 0.254 0.271 0.301]; + + % magnitude of linear transfer function normalized at 1 kHz + params.L_U = [-31.6 -27.2 -23.0 -19.1 -15.9 -13.0 -10.3 -8.1 ... + -6.2 -4.5 -3.1 -2.0 -1.1 -0.4 0.0 0.3 0.5 0.0 -2.7 ... + -4.1 -1.0 1.7 2.5 1.2 -2.1 -7.1 -11.2 -10.7 -3.1]; + + % threshold of hearing + params.T_f = [78.5 68.7 59.5 51.1 44.0 37.5 31.5 26.5 22.1 17.9... + 14.4 11.4 8.6 6.2 4.4 3.0 2.2 2.4 3.5 1.7 -1.3 -4.2... + -6.0 -5.4 -1.5 6.0 12.6 13.9 12.3]; + + %% Calculate + + % determine frequency range + if isempty(fq) + f = params.f; + else + f = fq; + end + + % output size + out_dims = [size(f) size(phon)]; + + % independent outputs + f_squeeze = zeros(numel(f),numel(phon)); + spl_squeeze = zeros(numel(f),numel(phon)); + + % iterate through phons + for p = 1:numel(phon) + % frequencies for phon level + f_squeeze(:,p) = f(:); + % interpolate reference parameters + if nargin>1 + if any(f_squeeze(:,p) > 12500) + % extrapolate - mirror 20Hz behaviour at 20kHz + f_r_extrap = [params.f 20000]; + alpha_f_r_extrap = [params.alpha_f params.alpha_f(1)]; + L_U_r_extrap = [params.L_U params.L_U(1)]; + T_f_r_extrap = [params.T_f params.T_f(1)]; + else + f_r_extrap = params.f; + alpha_f_r_extrap = params.alpha_f; + L_U_r_extrap = params.L_U; + T_f_r_extrap = params.T_f; + end + % interpolate parameters + alpha_f = interp1(f_r_extrap, alpha_f_r_extrap, f_squeeze(:,p)', 'spline', 'extrap'); + L_U = interp1(f_r_extrap, L_U_r_extrap, f_squeeze(:,p)', 'spline', 'extrap'); + T_f = interp1(f_r_extrap, T_f_r_extrap, f_squeeze(:,p)', 'spline', 'extrap'); + else + alpha_f = params.alpha_f; + L_U = params.L_U; + T_f = params.T_f; + end + % calculate SPL + A_f = 0.00447 * ((10^(0.025*phon(p)))-1.15) + ... + ((0.4*(10.^(((T_f+L_U)./10)-9))).^alpha_f); + if phon(p) > 0 + spl_squeeze(:,p) = ((10./alpha_f).*log10(A_f)) - L_U + 94; + else + spl_squeeze(:,p) = T_f; + end + end + + % reshape outputs + f = reshape(f_squeeze,out_dims); + spl = reshape(spl_squeeze,out_dims); + + % remove singleton dimensions if requested + if sq + f = squeeze(f); + spl = squeeze(spl); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/itd2azimuth.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/itd2azimuth.m new file mode 100644 index 0000000000000000000000000000000000000000..7f9bb6b7d597572c346fcce46d53675991d6c143 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/itd2azimuth.m @@ -0,0 +1,31 @@ +function azimuth = itd2azimuth(itd,f) +%ITD2AZIMUTH Convert ITD to azimuth +% +% AZIMUTH = IOSR.AUDITORY.ITD2AZIMUTH(ITD,F) converts the interaural time +% difference ITD (in seconds) at frequency F (in Hz) to AZIMUTH (in +% degrees) according to Kuhn's model [1]. +% +% References +% +% [1] Kuhn, G.F. (1977), Model for the interaural time differences in the +% azimuthal plane, The Journal of the Acoustical Society of America +% 62, 1, 157-167. +% +% See also IOSR.AUDITORY.AZIMUTH2ITD, IOSR.AUDITORY.FREQMULTI. + +% Copyright 2016 University of Surrey. + + assert(isnumeric(itd), 'iosr:itd2azimuth:invalidItd', 'ITD must be numeric') + assert((isscalar(f) | isscalar(itd)) | numel(f)==numel(itd),... + 'iosr:itd2azimuth:invalidInputs', ... + 'F or ITD must be a scalar, or F and ITD must be the same size') + + % Check sanity of ITDs + assert(all(itd<=iosr.auditory.azimuth2itd(90,f)),... + 'iosr:itd2azimuth:invalidItd', ... + 'ITDs greater than maximum ITD [=iosr.auditory.azimuth2itd(90,f)] have been specified.') + + czero = 344; + azimuth = asind((itd.*czero)./(iosr.auditory.freqMulti(f).*0.091)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/lindemannInh.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/lindemannInh.m new file mode 100644 index 0000000000000000000000000000000000000000..8a1aa25a04f80842f707f40518ddd77f86bba1dc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/lindemannInh.m @@ -0,0 +1,118 @@ +function [L_l,R_l] = lindemannInh(L,R,fs,c_inh,dim) +%LINDEMANNINH Signal pre-processing for Lindemann's cross-correlation +% +% [L_L,R_L] = IOSR.AUDITORY.LINDEMANNINH(L,R,FS) pre-processes left L and +% right R signals for the cross-correlation function based on Lindemann's +% precedence model [1,2]. A crucial parameter for Lindemann's model is +% the "operating point", which controls the amount of inhibition. The +% parameter is actually a function of the input related to its RMS level. +% After half-wave rectifying and filtering the input signals L and R +% (sampled at FS Hz) along the first non-singleton dimension, this +% function applies a gain related to the inhibition parameter C_INH +% (default is 0.3). The gain is identical for all rows, columns, etc. +% Lastly, values outside of the interval [0,1] are not permitted in +% Lindemann's model and hence these values are clipped. +% +% [L_L,R_L] = IOSR.AUDITORY.LINDEMANNINH(L,R,FS,C_INH) uses the specified +% inhibition parameter C_INH. The value must be in the interval [0,1]. +% +% [L_L,R_L] = IOSR.AUDITORY.LINDEMANNINH(L,R,FS,C_INH,DIM) pre-processes +% L and R along the dimension DIM. +% +% References +% +% [1] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. I. Simulation of lateralization +% for stationary signals, The Journal of the Acoustical Society of +% America 80, 6, 1608-1622. +% +% [2] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. II. The law of the first wave +% front, The Journal of the Acoustical Society of America 80, 6, +% 1623-1630. +% +% Further reading +% +% Hummersone, C., Mason, R., Brookes, T. (2013), A comparison of +% computational precedence models for source separation in +% reverberant environments, The Journal of the Audio Engineering +% Society 61, 7/8, 508-520. +% +% See also IOSR.AUDITORY.XCORRLINDEMANN. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(isequal(size(L),size(R)), 'iosr:lindemannInh:invalidInputs', 'L and R arrays must be the same size') + assert(isscalar(fs), 'iosr:lindemannInh:invalidFs', 'FS must be a scalar') + + % default dim + if nargin<5 + dim = find(size(L)>1,1,'first'); + end + + %% process + + % half-wave rectify + L_l = hwr(L); + R_l = hwr(R); + + % filter + cutofffreq=800; + [b,a] = butter(1,cutofffreq*2/fs); + L_l = filter(b,a,L_l,[],dim); + R_l = filter(b,a,R_l,[],dim); + + % inhibition parameter + if nargin < 4 + c_inh = .3; + else + assert(isscalar(c_inh) & isnumeric(c_inh), 'iosr:lindemannInh:invalidCinh', 'c_inh must be a scalar'); + assert(c_inh>=0 || c_inh<=1, 'iosr:lindemannInh:invalidX', 'c_inh must be in the interval (0,1].') + end + + % gain + c_gamma_L = calc_gamma(L,dim); + c_gamma_R = calc_gamma(R,dim); + c_gamma = max([c_gamma_L(:); c_gamma_R(:)]); + + % apply parameters + L_l = apply_gamma(L_l,c_inh,c_gamma); + R_l = apply_gamma(R_l,c_inh,c_gamma); + + % restrict range + L_l = clip(L_l); + R_l = clip(R_l); + +end + +function y = hwr(x) +%HWR half-wave rectify + + y = max(x,0); + +end + +function gamma = calc_gamma(x,dim) +%CALC_GAMMA calculate the gamma + + gamma = sqrt(2).*iosr.dsp.rms(x,dim); + +end + +function y = apply_gamma(x,c_inh,c_gamma) +%APPLY_GAMMA apply gamma to achieve inhibition parameter + + y = (c_inh/c_gamma).*x; + +end + +function y = clip(x) +%CLIP clip input data to [0,1] interval + + y = x; + y(y<0) = 0; + y(y>1) = 1; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/loudWeight.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/loudWeight.m new file mode 100644 index 0000000000000000000000000000000000000000..51e34d26f702d816ed40bf7f3391a2c73e867808 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/loudWeight.m @@ -0,0 +1,121 @@ +function g = loudWeight(f,phon) +%LOUDWEIGHT Calculate loudness weighting coefficients +% +% G = IOSR.AUDITORY.LOUDWEIGHT(F) returns loudness-weighting linear- +% magnitude coefficients for frequencies F (Hz). The function is based on +% the loudness at 65 phons defined in ISO 226:2003. The coefficients are +% scaled such that the G = 1 when F = 1000. +% +% G = IOSR.AUDITORY.LOUDWEIGHT(F,PHON) returns loudness weighting +% coefficients at the loudness level PHON. PHON should be a scalar and, +% according to the standard, is only valid at all frequencies such that +% 20<=PHON<80 (although the function will return extrapolated +% coefficients outside of this range). +% +% The input f may be an array of any size. The outputs will be the same +% size as f, with coefficients calculated for each element. +% +% G = IOSR.AUDITORY.LOUDWEIGHT(F,METHOD) returns loudness weighting +% coefficients for a variety of methods. Specifying METHOD as 'A', 'C', +% or 'Z' selects frequency weighting curves defined in IEC 61672-1:2013; +% 'ISO-226' selects a loudness weighting curve derived from ISO 226:2003 +% at 65 phons; 'B' selects a frequency weighting curve defined in IEC +% 60651:1979; 'D' selects a weighting curve defined in IEC 537:1976. +% +% See also IOSR.AUDITORY.ISO226, IOSR.AUDITORY.DUPWEIGHT. + +% Copyright 2016 University of Surrey. + + %% Check input + + assert(all(f(:)>=0), 'iosr:loudWeight:invalidF', 'f should be greater than or equal to zero!') + + if nargin<2 + phon = 65; + end + + if ischar(phon) + method = phon; + if strcmpi(method,'iso-226') + phon = 65; + end + elseif isnumeric(phon) + method = 'iso-226'; + assert(isscalar(phon), 'iosr:loudWeight:invalidPhon', 'phon must be a scalar.') + else + error('iosr:loudWeight:invalidArg','Second argument should be a scalar or char array.') + end + + %% coefficients + + fr = 1000; + fL = 10^1.5; + fH = 10^3.9; + fA = 10^2.45; + D = sqrt(0.5); + b = (1/(1-D)) * ((fr^2) + (((fL^2)*(fH^2))/(fr^2)) - (D*((fL^2)+(fH^2)))); + c = (fL^2)*(fH^2); + f1 = sqrt((-b - sqrt((b^2) - (4*c))) / (2)); + f4 = sqrt((-b + sqrt((b^2) - (4*c))) / (2)); + f2 = ((3 - sqrt(5)) / 2) * fA; + f3 = ((3 + sqrt(5)) / 2) * fA; + + %% Calculate weighting coefficients + + switch lower(method) + case 'a' + g = a_weighting(f); + case 'b' + g = b_weighting(f); + case 'c' + g = c_weighting(f); + case 'd' + g = d_weighting(f); + case 'z' + g = z_weighting(f); + case 'iso-226' + % calculate weighting coefficients + gdB = iosr.auditory.iso226(phon, 1000) - ... + squeeze(iosr.auditory.iso226(phon, f)); + g = 10.^(gdB./20); + otherwise + error('iosr:loudWeight:unknownMethod','Unknown method.') + end + + function w = a_weighting(f) + %A_WEIGHTING return A-weighting magnitude coefficients + function w = calculate(f) + w = ((f4^2).*(f.^4))./... + ( ((f.^2)+(f1^2)) .* sqrt((f.^2)+(f2^2)) .* sqrt((f.^2)+(f3^2)) .* ((f.^2)+(f4^2)) ); + end + w = calculate(f)./calculate(1000); + end + + function w = b_weighting(f) + %B_WEIGHTING return B-weighting magnitude coefficients + w = ((12200^2).*(f.^3))./... + (((f.^2)+(20.6^2)).*sqrt((f.^2)+(158.5^2)).*((f.^2)+(12200^2))); + end + + function w = c_weighting(f) + %C_WEIGHTING return C-weighting magnitude coefficients + function w = calculate(f) + w = ((f4^2).*(f.^2)) ./... + ( ((f.^2)+(f1^2)) .* ((f.^2)+(f4^2)) ); + end + w = calculate(f)./calculate(1000); + end + + function w = d_weighting(f) + %D_WEIGHTING return D-weighting magnitude coefficients + hf = (((1037918.48-(f.^2)).^2)+(1080768.16.*(f.^2)))./... + (((9837328-(f.^2)).^2)+(11723776.*(f.^2))); + w = (f./(6.8966888496476*(10^(-5)))).*sqrt(hf./(((f.^2)+79919.29).*((f.^2)+1345600))); + end + + function w = z_weighting(f) + %Z_WEIGHTING return Z-weighting magnitude coefficients + w = ones(size(f)); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/makeErbCFs.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/makeErbCFs.m new file mode 100644 index 0000000000000000000000000000000000000000..e5d35e48238fa2e150cd3646cfc5a144969551e2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/makeErbCFs.m @@ -0,0 +1,21 @@ +function cfs = makeErbCFs(mincf,maxcf,numchans) +%MAKEERBCFS Make a series of center frequencies equally spaced in ERB-rate. +% +% This function makes a vector of center frequenies equally spaced on the +% ERB-rate scale. +% +% CFS = IOSR.AUDITORY.MAKEERBCFS(MINCF,MAXCF,NUMCHANS) creates NUMCHANS +% centre frequencies between MINCF and MAXCF. +% +% Adapted from code written by: Guy Brown, University of Sheffield, and +% Martin Cooke. +% +% See also IOSR.AUDITORY.ERBRATE2HZ, IOSR.AUDITORY.HZ2ERBRATE. + +% Copyright 2016 University of Surrey. + + cfs = iosr.auditory.erbRate2hz(... + linspace(iosr.auditory.hz2erbRate(mincf),... + iosr.auditory.hz2erbRate(maxcf),numchans)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/meddisHairCell.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/meddisHairCell.m new file mode 100644 index 0000000000000000000000000000000000000000..5f776f8199fe071d64e0f5d7f5ea67498e893f68 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/meddisHairCell.m @@ -0,0 +1,76 @@ +function y = meddisHairCell(data,sampleRate,subtractSpont) +% Calculate Ray Meddis' hair cell model for a number of channels. +% +% y = iosr.auditory.meddisHairCell(data,sampleRate) +% +% This function calculates Ray Meddis' hair cell model for a +% number of channels. Data is arrayed as one channel per +% row. All channels are done in parallel (but each time step +% is sequential) so it will be much more efficient to +% process lots of channels at once. +% +% (c) 1998 Interval Research Corporation +% 12/11/98: Changed h and added comment at suggestion of +% Alain de Cheveigne + +if (nargin<3), subtractSpont=0; end + +% Parameters from Meddis' April 1990 JASA paper. +M = 1; +A = 5; +B = 300; +g = 2000; +y = 5.05; +l = 2500; +r = 6580; +x = 66.31; +h = 50000; % This parameter scales the discharge rate. Adjust as necessary. + % In combination with the gammatone filterbank (ERBFilterBank), + % h=50000 will produce a steady-state average discharge + % probability of about 135 spikes/s within the 1kHz channel, + % for an input consisting of a 1 kHz sinewave at 60 dB SPL + % (0 dB SPL corresponds to an RMS level of 1.0 at the + % input of the gammatone filter). Scaling and constant + % courtesy of Alain de Cheveigne' + + +% Internal constants +dt = 1/sampleRate; +gdt = g*dt; +ydt = y*dt; +ldt = l*dt; +rdt = r*dt; +xdt = x*dt; +[numChannels, dataLength] = size(data); + +% Initial values +kt = g*A/(A+B); +spont = M*y*kt/(l*kt+y*(l+r)); +c = spont * ones(numChannels,1); +q = c*(l+r)/kt; +w = c*r/x; +zeroVector = zeros(numChannels,1); + +% Now iterate through each time slice of the data. Use the +% max function to implement the "if (0>" test. +y = zeros(numChannels, dataLength); +for i = 1:dataLength + limitedSt = max(data(:,i)+A,0); + kt = gdt*limitedSt./(limitedSt+B); + replenish = max(ydt*(M-q),zeroVector); + eject = kt.*q; + loss = ldt.*c; + reuptake = rdt.*c; + reprocess = xdt.*w; + + q = q + replenish - eject + reprocess; + c = c + eject - loss - reuptake; + w = w + reuptake - reprocess; + y(:,i) = c; +end + +y = h .* y; + +if (subtractSpont > 0) + y=max(0,y-spont); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/perceptualCentroid.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/perceptualCentroid.m new file mode 100644 index 0000000000000000000000000000000000000000..40bcd81ee29acd4d1339d15aed4bfe067e7b7792 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/perceptualCentroid.m @@ -0,0 +1,326 @@ +function [PCmean,PCstd,PCmax,PCmin,N] = perceptualCentroid(x,fs,varargin) +%PERCEPTUALCENTROID Perceptual spectral centroid +% +% PCMEAN = IOSR.AUDITORY.PERCEPTUALCENTROID(X,FS) calculates the spectral +% centroid of signal X, sampled at FS, with respect to mel-frequency. +% +% The algorithm first calculates the spectrogram of X; each segment has +% the maximum of length(X)/8 or 2048 samples, calculated with 50% overlap +% and windowed with a hamming window. The spectrogram function is the +% built-in Matlab function SPECTROGRAM. The centroid is calculated with +% respect to mels by converting the FFT bin frequencies to mels. PCMEAN +% is the mean of the perceptual spectral centroids calculated for each +% segment. The perceptual spectral centroid can also be calculated using +% ERBs, cents, or hertz (see below). +% +% X can be a vector, matrix, or multidimensional array; +% PERCEPTUALCENTROID will operate along the first non-signleton +% dimension, and return a value for each corresponding row/column/etc. +% +% PCMEAN = IOSR.AUDITORY.PERCEPTUALCENTROID(X,FS,'PARAMETER',VALUE) +% allows numerous parameters to be specified. These parameters are:- +% 'cref' : {27.5} | scalar +% Specifies the reference frequency when calulating the centroid +% in terms of cents. +% 'dim' : {first non-singleton dimension} | integer +% Specify the dimension over which to calculate the perceptual +% spectral centroid. +% 'loudness' : {'none'} | 'A' | 'B' | 'C' | 'D' | 'ISO-226' +% Specifies whether loudness weighting is applied to the spectrum +% prior to the centroid calculation. The default is for no +% weighting to be applied. 'A', 'B', 'C', and 'D' correspond to +% frequency weighting curves defined in IEC 61672:2003; 'ISO-226' +% applies loudness weighting derived from ISO 226:2003. +% 'nfft' : {max([length(x)/2, 2048])} | integer +% Specifies SPECTROGRAM's FFT size. +% 'noverlap' : {nfft/2} | integer +% Specifies the number of samples over which SPECTROGRAM's +% segments overlap. +% 'output' : {'units'} | 'hz' +% Specifies whether the output data are in Hz ('hz') or in units +% determined by the 'scale' option ('units') (default). +% 'phon' : {65} | scalar +% Specifies the loudness level if using ISO 226:2003-based +% loudness weighting. +% 'scale' : {'mel'} | 'linear' | 'erb' | 'cents' +% Specifies frequency scale use to calculate the centroid. 'mel' +% uses the mel-frequency scale, 'linear' uses a linear frequency +% scale (corresponding to the traditional spectral centroid +% measure), 'erb' uses the equivalent-rectangular-bandwidth-rate +% scale, and cents uses a scale based on musical cents with +% respect to A-1 (27.5 Hz). +% 'window' : {hamming(nfft)} | vector +% Specifies the window applied to each SPECTROGRAM segment. +% +% [PCMEAN,PCSTD,PCMAX,PCMIN,N] = ... returns additional information:- +% PCMEAN : as described above. +% PCSTD : the standard deviation of the perceptual spectral +% centroids. +% PCMAX : the maximum of the perceptual spectral centroids. +% PCMIN : the minimum of the perceptual spectral centroids. +% N : the sample size for each statistic. +% +% For more information about the FFT calculation and its options, consult +% the SPECTROGRAM documentation. +% +% Examples +% +% Example 1: Calculate the mel-frequency spectral centroid of random +% noise: +% +% fs = 44100; +% x = randn(fs,1); +% PC = iosr.auditory.perceptualCentroid(x,fs); +% +% Example 2: Calculate the ERB-spaced spectral centroid of random +% noise with the output in Hertz: +% +% PC = iosr.auditory.perceptualCentroid(x,fs,... +% 'scale','erb','output','hz'); +% +% Example 3: Calculate the musically-spaced spectral centroid of +% random noise using a 4096-point Hann window: +% +% PC = iosr.auditory.perceptualCentroid(x,fs,... +% 'scale','cents','window',hann(4096)); +% +% Authors: Chris Hummersone & Kirsten Hermes, 2014 +% +% See also SPECTROGRAM. + +% Copyright 2016 University of Surrey. + + %% read inputs and make default assignments + + assert(~isscalar(x), 'iosr:perceptualCentroid:invalidX', '''X'' cannot be a scalar') + + dims = size(x); + + propNames = {'dim','nfft','noverlap','window','scale','output','cref','loudness','phon'}; % permitted prop names + + options = struct; + % read parameter/value options + if nargin>2 % if parameters are specified + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:perceptualCentroid:nameValuePairs','PERCEPTUALCENTROID needs propertyName/propertyValue pairs following the x and fs arguments.') + end + % write parameters to options struct + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + if any(strcmpi(pair{1},propNames)) + propName = char(propNames(find(strcmpi(pair{1},propNames),1,'last'))); + options.(propName) = pair{2}; + else + error('iosr:perceptualCentroid:unknownOption',['Unknown option ''' pair{1} '''']); + end + end + end + + % other parameters + dim = getProperty(options,'dim',find(dims>1,1,'first')); + assert(dim>0 && dim<=length(dims) && isscalar(dim) && round(dim)==dim,... + 'iosr:perceptualCentroid:invalidDim', ... + '''dim'' must be greater than zero and less than or equal to the number of dimensions in X.'); + + % determine window and nfft + defWinHandle = @hamming; % default window function + [nfft,nfft_set] = getProperty(options,'nfft',max([2048,floor(size(x,dim)/8)])); + [window,win_set] = getProperty(options,'window',defWinHandle(nfft)); + + if win_set + % window is specified + if isscalar(window) + window = defWinHandle(window); + end + if ~nfft_set + nfft = length(window); + end + if nfft~=length(window) + error('iosr:perceptualCentroid:invalidFFTlength','NFFT must be equal to the window length.') + end + else + % window is not specified + window = defWinHandle(nfft); + end + + % other parameters + noverlap = getProperty(options,'noverlap',floor(nfft/2)); + scale = getProperty(options,'scale','mel'); + output = getProperty(options,'output','units'); + cref = getProperty(options,'cref',27.5); + loudness = getProperty(options,'loudness','none'); + + % tests + assert(noverlap<min([nfft,length(window)]), 'iosr:perceptualCentroid:invalidNoverlap', '''noverlap'' must be less than ''nfft'' and the window length.'); + assert(isscalar(cref) && cref>0, 'iosr:perceptualCentroid:invalidCref', '''cref'' must be greater than 0.'); + + %% permute and rehape x to operate down columns + + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x2 = rearrange(x,order,[dims_shift(1) numel(x)/dims_shift(1)]); + + %% determine functions + + fHandleDoNothing = @(x,~) (x); + + % choose frequency transformation + switch lower(scale) + case 'linear' + fHandleFromF = fHandleDoNothing; + fHandleToF = fHandleDoNothing; + case 'mel' + fHandleFromF = @frequency2mel; + fHandleToF = @mel2frequency; + case 'erb' + fHandleFromF = @frequency2erb; + fHandleToF = @erb2frequency; + case 'cents' + fHandleFromF = @frequency2cents; + fHandleToF = @cents2frequency; + otherwise + error('iosr:perceptualCentroid:unknownScale',['Requested scale ''' scale ''' not recognised. Options are ''linear'', ''mel'', ''erb'', or ''cents''.']); + end + + % warn if cref but scale~=cents + if ~strcmpi(scale,'cents') && ... + any(cell2mat(strfind(lower(varargin(cellfun(@ischar,varargin))),'cref'))) + warning('iosr:perceptualCentroid:cref','Option ''cref'' only affects the output when ''scale'' is set to ''cents''.') + end + + %% calculate centroid and stats + + % pre-allocate outputes + PCmean = zeros(1,size(x2,2)); + PCstd = zeros(1,size(x2,2)); + PCmax = zeros(1,size(x2,2)); + PCmin = zeros(1,size(x2,2)); + N = zeros(1,size(x2,2)); + + % determine output conversion + switch lower(output) + case 'hz' + % use fHandleToF + case 'units' + fHandleToF = fHandleDoNothing; + otherwise + error('iosr:perceptualCentroid:unknownUnits',['Requested output ''' output ''' not recognised. Options are ''hz'', or ''units''.']); + end + + % determine phon, if relevant + switch lower(loudness) + case 'iso-226' + phon = getProperty(options,'phon',65); + otherwise + if isfield(options,'phon') + warning('iosr:perceptualCentroid:phon','''phon'' option has no effect unless using ''ISO-226'' loudness weighting.') + end + end + + % determine loudness weighting + switch lower(loudness) + case 'none' + w_l = @(x) ones(size(x)); + case 'a' + w_l = @(x) iosr.auditory.loudWeight(x,'a'); + case 'b' + w_l = @(x) iosr.auditory.loudWeight(x,'b'); + case 'c' + w_l = @(x) iosr.auditory.loudWeight(x,'c'); + case 'd' + w_l = @(x) iosr.auditory.loudWeight(x,'d'); + case 'iso-226' + w_l = @(x) iosr.auditory.loudWeight(x,phon); + otherwise + error('iosr:perceptualCentroid:unknownLoudness',['Requested loudness weighting ''' loudness ''' not recognised. Options are ''none'', or ''A''.']); + end + + for c = 1:size(x2,2) % across the dim in input + % caluclate spectrogram + [X,f] = spectrogram(x2(:,c),window,noverlap,nfft,fs); + % ignore frequencies greater than Nyquist + IX = f<=fs/2; + f = f(IX); + % convert frequencies + g = fHandleFromF(f,cref); + % calculate magnitude + mag = abs(X(IX,:)); + % calculate loudness weighting + loud = w_l(f); + % pre-allocate temp centroid values + centroid = zeros(1,size(X,2)); + for d = 1:size(X,2) % iterate through spectrogram windows + centroid(d) = fHandleToF(sum((loud.*mag(:,d)).*g)./sum(loud.*mag(:,d)),cref); + end + centroid(isnan(centroid)) = []; % if the original audio has parts of silence, the spectrogram windows contain only zeros which lead to NaN in centroid calculation. These columns are removed. + % calculate stats + PCmean(c) = mean(centroid); + PCstd(c) = std(centroid); + PCmax(c) = max(centroid); + PCmin(c) = min(centroid); + N(c) = size(X,2); + end + + %% inversely permute output back to input dimensions + + PCmean = irearrange(PCmean,order,[1 dims_shift(2:end)]); + PCstd = irearrange(PCstd,order,[1 dims_shift(2:end)]); + PCmax = irearrange(PCmax,order,[1 dims_shift(2:end)]); + PCmin = irearrange(PCmin,order,[1 dims_shift(2:end)]); + N = irearrange(N,order,[1 dims_shift(2:end)]); + +end + +function f = mel2frequency(m,~) +%MEL2FREQUENCY convert mel to frequency + f = 700.*(exp(m./1127)-1); +end + +function m = frequency2mel(f,~) +%FREQUENCY2MEL convert frequency to mel + m = 1127.*log(1+(f./700)); +end + +function f = erb2frequency(b,~) +%ERB2FREQUENCY convert ERB to frequency + f = (10.^(b./21.4)-1)./0.00437; +end + +function b = frequency2erb(f,~) +%FREQUENCY2ERB convert frequency to ERB + b = 21.4.*log10(1+(0.00437.*f)); +end + +function f = cents2frequency(c,cref) +%CENTS2FREQUENCY convert cents to frequency + f = cref.*(2.^(c./1200)-eps); +end + +function c = frequency2cents(f,cref) +%FREQUENCY2CENTS convert frequency to cents + c = 1200.*log2((f./cref)+eps); +end + +function [propValue,isset] = getProperty(options,propName,default) +%GETPROPERTY return property/default value + if isfield(options,propName) + propValue = options.(propName); + isset = true; + else + propValue = default; + isset = false; + end +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/perceptualCentroid2.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/perceptualCentroid2.m new file mode 100644 index 0000000000000000000000000000000000000000..bb9352a71516821afc18914ac5885c83e8ae3e21 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/perceptualCentroid2.m @@ -0,0 +1,275 @@ +function pc = perceptualCentroid2(x,fs,varargin) +%PERCEPTUALCENTROID2 Alternative perceptual spectral centroid +% +% PC = IOSR.AUDITORY.PERCEPTUALCENTROID2(X,FS) calculates the spectral +% centroid of signal X, sampled at FS, with respect to mel-frequency. +% +% The algorithm first calculates the long-term average spectrum (LTAS) of +% X according to IOSR.DSP.LTAS via the short-time Fourier transform +% (STFT). The perceptual centroid is then calculated using the LTAS. This +% is in contrast to IOSR.AUDITORY.PERCEPTUALCENTROID, which calculates +% the perceptual centroid for a series of spectrogram segments, and then +% takes the average (and other statistics). +% +% X can be a vector, matrix, or multidimensional array; +% PERCEPTUALCENTROID2 will operate along the first non-signleton +% dimension, and return a value for each corresponding row/column/etc. +% +% PC = IOSR.AUDITORY.PERCEPTUALCENTROID2(X,FS,'PARAMETER',VALUE) allows +% numerous parameters to be specified. These parameters are:- +% 'cref' : {27.5} | scalar +% Specifies the reference frequency when calulating the centroid +% in terms of cents. +% 'dim' : {first non-singleton dimension} | integer +% Specify the dimension over which to calculate the perceptual +% spectral centroid. +% 'hop' : {512} | integer +% Specifies the hop size of the STFT. +% 'loudness' : {'none'} | 'A' | 'B' | 'C' | 'D' | 'ISO-226' +% Specifies whether loudness weighting is applied to the spectrum +% prior to the centroid calculation. The default is for no +% weighting to be applied. 'A', 'B', 'C', and 'D' correspond to +% frequency weighting curves defined in IEC 61672:2003; 'ISO-226' +% applies loudness weighting derived from ISO 226:2003. +% 'noct' : {12} | scalar +% Apply 1/noct-octave smoothing to the frequency spectrum. +% Setting 'noct' to 0 results in no smoothing. +% 'output' : {'units'} | 'hz' +% Specifies whether the output data are in Hz ('hz') or in units +% determined by the 'scale' option ('units') (default). +% 'phon' : {65} | scalar +% Specifies the loudness level if using ISO 226:2003-based +% loudness weighting. +% 'scale' : {'mel'} | 'linear' | 'erb' | 'cents' +% Specifies frequency scale use to calculate the centroid. 'mel' +% uses the mel-frequency scale, 'linear' uses a linear frequency +% scale (corresponding to the traditional spectral centroid +% measure), 'erb' uses the equivalent-rectangular-bandwidth-rate +% scale, and cents uses a scale based on musical cents with +% respect to A-1 (27.5 Hz). +% 'window' : {hamming(1024)} | vector +% Specifies the window applied to each STFT segment. +% +% Examples +% +% Example 1: Calculate the mel-frequency spectral centroid of random +% noise: +% +% fs = 44100; +% x = randn(fs,1); +% PC = iosr.auditory.perceptualCentroid2(x,fs); +% +% Example 2: Calculate the ERB-spaced spectral centroid of random +% noise with the output in Hertz: +% +% PC = iosr.auditory.perceptualCentroid2(x,fs,... +% 'scale','erb','output','hz'); +% +% Example 3: Calculate the musically-spaced spectral centroid of +% random noise using a 4096-point Hann window: +% +% PC = iosr.auditory.perceptualCentroid2(x,fs,... +% 'scale','cents','window',hann(4096)); +% +% Authors: Chris Hummersone & Kirsten Hermes, 2014 +% +% See also IOSR.DSP.LTAS, IOSR.AUDITORY.PERCEPTUALCENTROID. + +% Copyright 2016 University of Surrey. + + %% read inputs and make default assignments + + assert(~isscalar(x), 'iosr:perceptualCentroid2:invalidX', '''X'' cannot be a scalar') + + dims = size(x); + + propNames = {'dim','hop','noct','window','scale','output','cref','loudness','phon'}; % permitted prop names + + options = struct; + % read parameter/value options + if nargin>2 % if parameters are specified + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:perceptualCentroid2:nameValuePairs','PERCEPTUALCENTROID2 needs propertyName/propertyValue pairs following the x and fs arguments.') + end + % write parameters to options struct + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + if any(strcmpi(pair{1},propNames)) + propName = char(propNames(find(strcmpi(pair{1},propNames),1,'last'))); + options.(propName) = pair{2}; + else + error('iosr:perceptualCentroid2:unknownOption',['Unknown option ''' pair{1} '''']); + end + end + end + + % other parameters + dim = getProperty(options,'dim',find(dims>1,1,'first')); + assert(dim>0 && dim<=length(dims) && isscalar(dim) && round(dim)==dim,... + 'iosr:perceptualCentroid2:invalidDim', ... + '''dim'' must be greater than zero and less than or equal to the number of dimensions in X.'); + + % other parameters + window = getProperty(options,'window',hamming(1024)); + hop = getProperty(options,'hop',512); + noct = getProperty(options,'noct',12); + scale = getProperty(options,'scale','mel'); + output = getProperty(options,'output','units'); + cref = getProperty(options,'cref',27.5); + loudness = getProperty(options,'loudness','none'); + + % tests + assert(isscalar(cref) && cref>0, 'iosr:perceptualCentroid2:invalidCref', '''cref'' must be greater than 0.'); + + %% permute and rehape x to operate down columns + + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x2 = rearrange(x,order,[dims_shift(1) numel(x)/dims_shift(1)]); + + %% determine functions + + fHandleDoNothing = @(x,~) (x); + + % choose frequency transformation + switch lower(scale) + case 'linear' + fHandleFromF = fHandleDoNothing; + fHandleToF = fHandleDoNothing; + case 'mel' + fHandleFromF = @frequency2mel; + fHandleToF = @mel2frequency; + case 'erb' + fHandleFromF = @frequency2erb; + fHandleToF = @erb2frequency; + case 'cents' + fHandleFromF = @frequency2cents; + fHandleToF = @cents2frequency; + otherwise + error('iosr:perceptualCentroid2:unknownScale',['Requested scale ''' scale ''' not recognised. Options are ''linear'', ''mel'', ''erb'', or ''cents''.']); + end + + % warn if cref but scale~=cents + if ~strcmpi(scale,'cents') && ... + any(cell2mat(strfind(lower(varargin(cellfun(@ischar,varargin))),'cref'))) + warning('iosr:perceptualCentroid2:cref','Option ''cref'' only affects the output when ''scale'' is set to ''cents''.') + end + + %% calculate centroid and stats + + % pre-allocate outputes + pc = zeros(1,size(x2,2)); + + % determine output conversion + switch lower(output) + case 'hz' + % use fHandleToF + case 'units' + fHandleToF = fHandleDoNothing; + otherwise + error('iosr:perceptualCentroid2:unknownUnits',['Requested output ''' output ''' not recognised. Options are ''hz'', or ''units''.']); + end + + % determine phon, if relevant + switch lower(loudness) + case 'iso-226' + phon = getProperty(options,'phon',65); + otherwise + if isfield(options,'phon') + warning('iosr:perceptualCentroid2:phon','''phon'' option has no effect unless using ''ISO-226'' loudness weighting.') + end + end + + % determine loudness weighting + switch lower(loudness) + case 'none' + w_l = @(x) ones(size(x)); + case 'a' + w_l = @(x) iosr.auditory.loudWeight(x,'a'); + case 'b' + w_l = @(x) iosr.auditory.loudWeight(x,'b'); + case 'c' + w_l = @(x) iosr.auditory.loudWeight(x,'c'); + case 'd' + w_l = @(x) iosr.auditory.loudWeight(x,'d'); + case 'iso-226' + w_l = @(x) iosr.auditory.loudWeight(x,phon); + otherwise + error('iosr:perceptualCentroid2:unknownLoudness',['Requested loudness weighting ''' loudness ''' not recognised. Options are ''none'', or ''A''.']); + end + + for c = 1:size(x2,2) % across the dim in input + % caluclate spectrogram + [X,f] = iosr.dsp.ltas(x2(:,c),fs,'win',window,'hop',hop,'noct',noct,'units','none'); + % ignore frequencies greater than Nyquist + IX = f<=fs/2; + f = f(IX); + % convert frequencies + g = fHandleFromF(f,cref); + % calculate magnitude + mag = sqrt(X(IX,:)); + % calculate loudness weighting + loud = w_l(f); + % calculate centroid + pc(c) = fHandleToF(sum((loud.*mag).*g)./sum(loud.*mag),cref); + end + + %% inversely permute output back to input dimensions + + pc = irearrange(pc,order,[1 dims_shift(2:end)]); + +end + +function f = mel2frequency(m,~) +%MEL2FREQUENCY convert mel to frequency + f = 700.*(exp(m./1127)-1); +end + +function m = frequency2mel(f,~) +%FREQUENCY2MEL convert frequency to mel + m = 1127.*log(1+(f./700)); +end + +function f = erb2frequency(b,~) +%ERB2FREQUENCY convert ERB to frequency + f = (10.^(b./21.4)-1)./0.00437; +end + +function b = frequency2erb(f,~) +%FREQUENCY2ERB convert frequency to ERB + b = 21.4.*log10(1+(0.00437.*f)); +end + +function f = cents2frequency(c,cref) +%CENTS2FREQUENCY convert cents to frequency + f = cref.*(2.^(c./1200)-eps); +end + +function c = frequency2cents(f,cref) +%FREQUENCY2CENTS convert frequency to cents + c = 1200.*log2((f./cref)+eps); +end + +function [propValue,isset] = getProperty(options,propName,default) +%GETPROPERTY return property/default value + if isfield(options,propName) + propValue = options.(propName); + isset = true; + else + propValue = default; + isset = false; + end +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/xcorrLindemann.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/xcorrLindemann.m new file mode 100644 index 0000000000000000000000000000000000000000..5745c9986ddea2c6223a50af4730dc6dc47b0cb3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/xcorrLindemann.m @@ -0,0 +1,110 @@ +function [c,lags] = xcorrLindemann(L,R,fs,maxlag,dim) +%XCORRLINDEMANN Cross-correlation based on Lindemann's precedence model +% +% C = IOSR.AUDITORY.XCORRLINDEMANN(L,R,FS) calculates the +% cross-correlation of vectors L and R, sampled at FS Hz, using a maximum +% cross-correlation lag of 0.001*fs samples (1 ms). The cross-correlation +% function is based on Lindemann's [1,2] precedence model. C is the same +% size as L or R, except that size(C,1) = 2*0.001*fs+1. +% +% C = IOSR.AUDITORY.XCORRLINDEMANN(L,R,FS,MAXLAG) calculates the +% cross-correlation using a maximum cross-correlation lag of MAXLAG +% samples. +% +% C = IOSR.AUDITORY.XCORRLINDEMANN(L,R,FS,MAXLAG,DIM) performs the +% cross-correlation along the dimension DIM. C is the same size as L or +% R, except that size(C,DIM) = 2*MAXLAG+1. +% +% [C,LAGS] = IOSR.AUDITORY.XCORRLINDEMANN(...) returns the lags, in +% seconds, over which the cross-correlation was calculated. +% +% References +% +% [1] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. I. Simulation of lateralization +% for stationary signals, The Journal of the Acoustical Society of +% America 80, 6, 1608-1622. +% +% [2] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. II. The law of the first wave +% front, The Journal of the Acoustical Society of America 80, 6, +% 1623-1630. +% +% See also IOSR.AUDITORY.LINDEMANNINH, XCORR. + +% Copyright 2016 University of Surrey. + + %% check input + assert(isequal(size(L),size(R)), 'iosr:xcorrLindemann:invalidSignals', 'L and R must be the same size'); + assert(isscalar(fs) & isnumeric(fs), 'iosr:xcorrLindemann:invalidFs', 'FS must be a scalar'); + + % check for maxlag + if nargin<4 + maxlag = 0.001*fs; + else + assert(isscalar(maxlag) & isnumeric(maxlag), 'iosr:xcorrLindemann:invalidMaxlag', 'MAXLAG must be a scalar'); + end + + % check for dim + dims = size(L); + if nargin<5 + dim = find(dims>1,1,'first'); + else + assert(isscalar(dim) && round(dim)==dim, 'iosr:xcorrLindemann:invalidDim', 'DIM must be an integer scalar') + end + + % check L and R have a valid range + if any(L(:)<0) || any(R(:)<0) || any(L(:)>1) || any(R(:)>1) + error('iosr:xcorrLindemann:inputOutOfRange','L and/or R contain values outside of the range [0,1]. This is not allowed. Use LINDEMANN_INH to pre-process the L and R inputs.') + end + + % check C function is compiled + iosr.general.checkMexCompiled('-largeArrayDims',fullfile(fileparts(mfilename('fullpath')),'xcorrLindemann_c.c')) + + %% re-arrange input + + % re-arrange array to operate along columns + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + L = rearrange(L,order,[dims_shift(1),numel(L)/dims_shift(1)]); + R = rearrange(R,order,[dims_shift(1),numel(R)/dims_shift(1)]); + + %% do cross-correlation + + % time constants + t_int = 5; % ms + t_inh = 10; % ms + + xcorr_length = round(2*maxlag)+1; % length of cross-correlation + c = zeros(xcorr_length,size(L,2)); % pre-allocate + for n = 1:size(L,2) + c(:,n) = iosr.auditory.xcorrLindemann_c(L(:,n),R(:,n),fs,maxlag,t_inh,t_int); + end + + %% return values + + % rearrange to match input dimensions + c = irearrange(c,order,[xcorr_length dims_shift(2:end)]); + + % return lags + if nargin>1 + lags = (-maxlag:maxlag)./fs; + end + +end + +function y = rearrange(x,dim_order,shape) +%REARRANGE rearrange data to 2-D matrix with target dim as column + + y = permute(x,dim_order); + y = reshape(y,shape); + +end + +function y = irearrange(x,dim_order,shape) +%IREARRANGE inverse rearrangement + + y = reshape(x,shape); + y = ipermute(y,dim_order); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/xcorrLindemann_c.c b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/xcorrLindemann_c.c new file mode 100644 index 0000000000000000000000000000000000000000..a215c98e93ba3ca55e8722f9bc4cdd899641af21 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+auditory/xcorrLindemann_c.c @@ -0,0 +1,143 @@ +/* Lindemann's precedence model. + * + * Copyright 2016 University of Surrey. + * + */ + +#include "math.h" +#include "mex.h" + +#define TEMP_ARRAY mxCreateDoubleMatrix((mwSize)length_c,(mwSize)1,mxREAL) +#define IN_ARRAY mxCreateDoubleMatrix((mwSize)n_sample,(mwSize)1,mxREAL) + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + /* ====================== INPUTS & SCALARS ====================== */ + + double *L = mxGetPr(prhs[0]), /* pointer to left signal input */ + *R = mxGetPr(prhs[1]), /* pointer to right signal input */ + fs = *mxGetPr(prhs[2]); /* samle frequency */ + + mwSize maxlag = *mxGetPr(prhs[3]); /* maximum lag */ + + double tinh = (*mxGetPr(prhs[4]))/1000.0, /* fade-off time constant */ + tint = (*mxGetPr(prhs[5]))/1000.0, /* integration time constant */ + td = 0.5*(1.0/fs), /* half sample period */ + alpha = exp(-td/tinh), /* fade-off factor */ + alpha2 = exp(-td/tint), /* integration factor */ + Mf = 6.0, /* fading constant for monaural sensitivity */ + wf = 0.035; /* monaural sensitivity of a correlator to the signal at the end of a delay line */ + + /* sizes */ + mwSize numsamples = mxGetM(prhs[0]), /* number of samples */ + length_c = (2*maxlag)+1, /* length of cross-correlation (2*maxlag)+1 */ + in_length = length_c+numsamples-1, /* length of input to cross-correlation */ + n_sample = 2*in_length-1; /* length of inhibited input to cross-correlation */; + + /* indices */ + mwIndex n, /* sample */ + m, /* lag */ + leftn, /* left samples to be cross-correlated */ + rightn; /* right samples to be cross-correlated */ + + /* ====================== TEMP ARRAYS ====================== */ + + /* monaural sensitivity functions */ + mxArray *wl_mx,*wr_mx; + wl_mx = TEMP_ARRAY; + wr_mx = TEMP_ARRAY; + double *wl = mxGetPr(wl_mx), + *wr = mxGetPr(wr_mx); + for ( m = 0; m < length_c; m++ ) { + wl[m] = wf*exp(-((double)m)/Mf); + wr[m] = wf*exp(((double)m-(double)length_c+1.0)/Mf); + } + + /* running cross-correlation */ + mxArray *k_mx; + k_mx = TEMP_ARRAY; + double *k = mxGetPr(k_mx); + + /* inhibited input to the cross-correlation */ + mxArray *lc_mx,*rc_mx; + lc_mx = TEMP_ARRAY; + rc_mx = TEMP_ARRAY; + double *lc = mxGetPr(lc_mx), + *rc = mxGetPr(rc_mx); + + /* input to cross-correlation */ + mxArray *lin_mx,*rin_mx; + lin_mx = IN_ARRAY; + rin_mx = IN_ARRAY; + double *lin = mxGetPr(lin_mx), + *rin = mxGetPr(rin_mx); + + /* inhibitory components */ + mxArray *il_mx,*ir_mx; + il_mx = TEMP_ARRAY; + ir_mx = TEMP_ARRAY; + double *il = mxGetPr(il_mx), + *ir = mxGetPr(ir_mx); + + /* dynamic inhibitory component for current and previous samples */ + mxArray *phin_mx,*phic_mx; + phin_mx = TEMP_ARRAY; + phic_mx = TEMP_ARRAY; + double *phin = mxGetPr(phin_mx), + *phic = mxGetPr(phic_mx); + + /* inhibited cross-correlation for current and previous samples */ + mxArray *sumn_mx,*sumc_mx; + sumn_mx = TEMP_ARRAY; + sumc_mx = TEMP_ARRAY; + double *sumn = mxGetPr(sumn_mx), + *sumc = mxGetPr(sumc_mx); + + /* ====================== OUTPUT ====================== */ + + plhs[0] = TEMP_ARRAY; + double *c_out = mxGetPr(plhs[0]); + + /* ====================== CROSS-CORRELATE ====================== */ + + for ( n = 0 ; n < numsamples ; n++ ) { + /* input to cross-correlation */ + lin[(2*n)] = L[n]; + rin[(2*n)] = R[n]; + } + for ( n = 0; n < n_sample; n++ ) { + for ( m = 0; m < 2*maxlag; m++ ) { + /* inhibit input to cross-correlation */ + lc[m] = lc[m+1]*il[m+1]; + rc[(2*maxlag)-m] = rc[(2*maxlag)-m-1]*ir[(2*maxlag)-m-1]; + } + lc[length_c-1] = lin[n]; + rc[0] = rin[n]; + /* cross-correlate */ + for ( m = 0; m < length_c; m++ ) { + k[m] = (wl[m]+(1.0-wl[m])*rc[m])*(wr[m]+(1.0-wr[m])*lc[m]); + phin[m] = k[m]+alpha*phic[m]*(1-k[m]); + phic[m]=phin[m]; + il[m]=(1.0-rc[m])*(1-phic[m]); + ir[m]=(1.0-lc[m])*(1-phic[m]); + sumn[m]=sumc[m]*alpha2+(1.0-alpha2)*k[m]; + sumc[m]=sumn[m]; + c_out[m] += sumn[m]; + } + } + /* Destroy mx arrays */ + mxDestroyArray(wl_mx); + mxDestroyArray(wr_mx); + mxDestroyArray(k_mx); + mxDestroyArray(lc_mx); + mxDestroyArray(rc_mx); + mxDestroyArray(il_mx); + mxDestroyArray(ir_mx); + mxDestroyArray(phin_mx); + mxDestroyArray(phic_mx); + mxDestroyArray(sumn_mx); + mxDestroyArray(sumc_mx); + mxDestroyArray(lin_mx); + mxDestroyArray(rin_mx); + return; +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/applyIdealMasks.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/applyIdealMasks.m new file mode 100644 index 0000000000000000000000000000000000000000..0aeee55f51cf3d08e1cadd351e51740199b2d3a5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/applyIdealMasks.m @@ -0,0 +1,116 @@ +function [z_irm,z_ibm,t] = applyIdealMasks(xt,xi,nfft,hop,fs) +%APPLYIDEALMASKS Calculate and apply ideal masks via STFT +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI) calculates the ideal ratio mask +% (IRM) and applies it to the mixture XT+XI, where XT is the target +% signal and XI is the interference signal. The IRM is calculated via the +% STFT using 1024-point windows with 512-point overlap. Z_IRM, XT, and XI +% are vectors. If XT and XI are of different lengths then the shorter +% signal is zero-padded in order to make them the same length; Z_IRM is +% the same length as XT and XI. +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI,NFFT) uses NFFT-length segments +% in the STFT. +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI,WINDOW) uses +% LENGTH(WINDOW)-length segments in the STFT and applies WINDOW to each +% segment. +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI,WINDOW,HOP) uses hop size HOP +% for the STFT. +% +% [Z_IRM,Z_IBM] = IOSR.BSS.APPLYIDEALMASKS(...) calculates the ideal +% binary mask (IBM) and applies it to the mixture, returning the result +% to Z_IBM. +% +% [Z_IRM,Z_IBM,T] = IOSR.BSS.APPLYIDEALMASKS(XT,XI,WINDOW,HOP,FS) uses +% sampling frequency FS to return the corresponding time T of each +% element in Z_IRM and Z_IBM. +% +% See also IOSR.DSP.STFT, IOSR.DSP.ISTFT, IOSR.BSS.IDEALMASKS, +% IOSR.BSS.APPLYMASKS. + +% Copyright 2016 University of Surrey. + + %% check input + + % check signals + assert(isvector(xt) && numel(xt)>1, 'iosr:applyIdealMasks:invalidXt', 'XT must be a vector') + assert(isvector(xi) && numel(xi)>1, 'iosr:applyIdealMasks:invalidXi', 'XI must be a vector') + + % make equal length + maxlength = max([length(xi) length(xt)]); + xt = pad(xt,maxlength); + xi = pad(xi,maxlength); + + % check nfft + if nargin<3 + nfft = 1024; + end + + % determine window + if numel(nfft)>1 + win = nfft; + assert(isvector(win), 'iosr:applyIdealMasks:invalidWin', 'WINDOW must be a vector') + nfft = length(win); + else + assert(round(nfft)==nfft && nfft>0, 'iosr:applyIdealMasks:invalidNfft', 'NFFT must be a positive integer') + win = hamming(nfft); + end + + % check x length + assert(length(xt)>=nfft, 'iosr:applyIdealMasks:invalidXt', 'XT must have at least NFFT samples') + assert(length(xi)>=nfft, 'iosr:applyIdealMasks:invalidXi', 'XI must have at least NFFT samples') + + % determine hop + if nargin<4 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:applyIdealMasks:invalidHop', 'HOP must be an integer') + assert(hop<=nfft && hop>0, 'iosr:applyIdealMasks:invalidHop', 'HOP must be less than or equal to NFFT, and greater than 0') + end + + % determine fs + if nargin<5 + fs = 1; + else + assert(isscalar(fs), 'iosr:applyIdealMasks:invalidFs', 'FS must be an scalar') + end + + %% calculate outputs + + % STFTs of signals and mixture + st = iosr.dsp.stft(xt,win,hop); + si = iosr.dsp.stft(xi,win,hop); + mix = iosr.dsp.stft(xt+xi,win,hop); + + % return ideal masks + [irm,ibm] = iosr.bss.idealMasks(st,si); + + % apply IRM + z_irm = iosr.bss.applyMask(mix,irm,nfft,hop,fs); + z_irm = pad(z_irm,maxlength); + + % apply IBM + if nargout>1 + z_ibm = iosr.bss.applyMask(mix,ibm,nfft,hop,fs); + z_ibm = pad(z_ibm,maxlength); + end + + % calculate t + if nargout>2 + t = (0:length(z_irm)-1)./fs; + end + +end + +function y = pad(x,dur) +%PAD Zero-pad a vector + + if length(x)<dur + y = [x(:); zeros(dur-length(x),1)]; + else + y = x(:); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/applyMask.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/applyMask.m new file mode 100644 index 0000000000000000000000000000000000000000..b84cec85ff3d3740afb3a02ef2cb133b50aef811 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/applyMask.m @@ -0,0 +1,64 @@ +function [z,t] = applyMask(s,m,nfft,hop,fs) +%APPLYMASK Apply a time-frequency mask to an STFT +% +% Z = IOSR.BSS.APPLYMASK(S,M) applies the time-frequency mask M to STFT +% S. S has dimensions [N,K] where N is the number of frequency bins and K +% is the number of time frames. The ISTFT is calculated using 1024-point +% FFTs and hop sizes of 512 points. +% +% Z = IOSR.BSS.APPLYMASK(S,M,NFFT) uses NFFT-length segments in the +% ISTFT. +% +% Z = IOSR.BSS.APPLYMASK(S,M,NFFT,HOP) uses hop size HOP for the ISTFT. +% +% [Z,T] = IOSR.BSS.APPLYMASK(S,M,NFFT,HOP,FS) uses sampling frequency FS +% to return the corresponding time T of each element in Z. +% +% See also IOSR.DSP.STFT, IOSR.DSP.ISTFT, IOSR.BSS.IDEALMASKS, +% IOSR.BSS.APPLYIDEALMASKS. + +% Copyright 2016 University of Surrey. + + %% check input + + % check input + if nargin<2 + error('iosr:applyMask:nargin','Not enough input arguments') + end + + % check compulsory inputs + assert(isequal(size(s),size(m)), 'iosr:applyMask:invalidInput', 'S and M must be the same size') + + % check nfft + if nargin<3 + nfft = 1024; + else + assert(isscalar(nfft) && round(nfft)==nfft && nfft>0, 'iosr:applyMask:invalidNfft', 'NFFT must be a positive scalar integer') + end + + % determine hop + if nargin<4 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:applyMask:invalidHop', 'HOP must be an integer') + assert(hop<=nfft && hop>0, 'iosr:applyMask:invalidHop', 'HOP must be less than or equal to NFFT, and greater than 0') + end + + % determine fs + if nargin<5 + fs = 1; + else + assert(isscalar(fs), 'iosr:applyMask:invalidFs', 'FS must be an scalar') + end + + %% calculate outputs + + % apply mask and return signal + z = iosr.dsp.istft(s.*m,nfft,hop); + + % return time + if nargout>1 + t = (0:length(z)-1)./fs; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/calcImr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/calcImr.m new file mode 100644 index 0000000000000000000000000000000000000000..7f88f3f793952507887a9dbbf789e001fecb9f97 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/calcImr.m @@ -0,0 +1,39 @@ +function IMR = calcImr(m,im) +%CALCIMR Calculates the Ideal Mask Ratio (IMR) +% +% IMR = IOSR.BSS.CALCIMR(M,IM) calculates the ideal mask ratio (IMR) from +% the calculated mask M and ideal mask IM. Masks can be logical or +% double, but must only contain values in the interval [0,1]. + +% Copyright 2016 University of Surrey. + + % check input + assert(nargin>1, 'iosr:calcImr:invalidInput', 'You need 2 masks to calculate IMR!') + assert(size(m,1)>1 & size(m,2)>1, 'iosr:calcImr:invalidMask', 'm must be a two-dimensional matrix') + assert(size(im,1)>1 & size(im,2)>1, 'iosr:calcImr:invalidMask', 'im must be a two-dimensional matrix') + assert(all(size(m)==size(im)), 'iosr:calcImr:invalidMask', 'Masks must be the same size!') + + % validate masks + m = check_mask(m); + im = check_mask(im); + + % calculate IMR + lamda = sum(sum(m.*im)); + rho = sum(sum(abs(m-im))); + + IMR = lamda/(lamda+rho); + +end + +function m = check_mask(m) +%CHECK_MASK validate mask + + if ~islogical(m) + if any(m(:)<0) || any(m(:)>1); + error('iosr:calcImr:maskValuesOutOfRange','Values outside of [0,1] were found.') + end + else % make numeric + m = +m; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/calcSnr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/calcSnr.m new file mode 100644 index 0000000000000000000000000000000000000000..ec6bec299d696485f513a4d388da17883ab780eb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/calcSnr.m @@ -0,0 +1,49 @@ +function snr = calcSnr(output,target) +%CALCSNR Calculate the separation SNR +% +% SNR = IOSR.BSS.CALCSNR(OUTPUT,TARGET) calculate the separation +% signal-to-noise ratio in dB for a re-synthesised output compared to the +% ideal target. OUTPUT and TARGET should be vectors of equal length. + +% Copyright 2016 University of Surrey. + + % check input + if ~isvector(output) + error('iosr:calcSnr:invalidOutput','''output'' must be a vector') + end + if ~isvector(target) + error('iosr:calcSnr:invalidTarget','''target'' must be a vector') + end + if numel(output)~=numel(target) + error('iosr:calcSnr:inputLengths','inputs must be the same length') + end + if size(output,1)==1 + output = output'; + end + if size(target,1)==1 + target = target'; + end + + % remove delay caused by convolution + cc = xcorr(output.^2,target.^2); + + delay = find(cc==max(cc))-length(output); + + if delay > 0 + target = [zeros(delay,1); target]; + output = [output; zeros(delay,1)]; + elseif delay < 0 + delay = -delay; + output = [zeros(delay,1); output]; + target = [target; zeros(delay,1)]; + end + + % account for arbitrary gain + if sum(abs(output(:))) > 0 + G = output\target; + output = output.*G; + end + + snr = 10*log10(sum(target.^2)/sum((output-target).^2)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/cfs2fcs.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/cfs2fcs.m new file mode 100644 index 0000000000000000000000000000000000000000..20aaddb624b1df21a65839e24e9d706782123e46 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/cfs2fcs.m @@ -0,0 +1,57 @@ +function fcs = cfs2fcs(cfs,fs) +%CFS2FCS Calculate gammatone crossover frequencies. +% +% FCS = IOSR.BSS.CFS2FCS(CFS,FS) calculates the crossover frequencies of a +% gammatone filterbank. The output fcs is the same size as CFS, with the +% last element being equal to fs/2. +% +% The crossover frequencies are determined empirically by measuring the +% impulse responses of the gammatone filters. +% +% See also IOSR.AUDITORY.GAMMATONEFAST, IOSR.AUDITORY.MAKEERBCFS. + +% Copyright 2016 University of Surrey. + + % Pre-allocate cut-off frequencies + fcs = zeros(size(cfs)); + fcs(end) = fs/2; + + % Create impulse to derive cut-offs empirically + imp_length = fs; + imp = zeros(imp_length,1); + imp(1) = 1; + + % Pre-allocate gammatone transfer functions + if mod(imp_length,2)==0 + z_length = (imp_length/2)+1; + else + z_length = (imp_length+1)/2; + end + gamma_TF = zeros(z_length,length(cfs)); + + % Filter impulses and calculate transfer functions. + for i = 1:length(cfs) + % filter + gamma_imp = iosr.auditory.gammatoneFast(imp,cfs,fs); + % transfer function + temp = abs(fft(gamma_imp)); + gamma_TF(:,i) = temp(1:z_length); + end + + f = ((0:z_length-1)./imp_length).*fs; + + % Find cross point of transfer functions. + for i = 1:length(cfs)-1 + IX = f>cfs(i) & f<cfs(i+1); + if sum(IX)>0 + f_temp = f(IX); + low_TF = gamma_TF(IX,i); + high_TF = gamma_TF(IX,i+1); + diff_TF = abs(high_TF-low_TF); + fcs(i) = f_temp(find(diff_TF==min(diff_TF),1,'first')); + else + fcs(i) = mean([cfs(i) cfs(i+1)]); + end + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/example.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/example.m new file mode 100644 index 0000000000000000000000000000000000000000..a1528e1eb8038c2e1fe3f6cfa98cb3d1705d2462 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/example.m @@ -0,0 +1,94 @@ +%% determine STFT parameters + +hop = 128; +nfft = 1024; +win = hann(nfft); + +%% load signals + +load('handel.mat','y','Fs') +xt = y; +load('laughter.mat','y','Fs') +xi = y; + +% crop xt +xt = xt(1:length(xi)); + +%% calculate and plot STFTs + +% calculate STFTs +[st,f,t] = iosr.dsp.stft(xt,win,hop,Fs); +si = iosr.dsp.stft(xi,win,hop,Fs); + +% calculate spectrograms +stlog = 20.*log10(abs(st)); +silog = 20.*log10(abs(si)); + +% calculate colormap limits +clim = [min([stlog(:); silog(:)]) max([stlog(:); silog(:)])]; + +% draw figures +figure +% +subplot(8,4,[1 2 5 6]) +imagesc(t,f,stlog) +set(gca,'ydir','normal','xticklabel',[],'clim',clim) +title('Target spectrogram') +ylabel('Frequency [Hz]') +ch = colorbar; +ylabel(ch,'Magnitude [dB]') +% +subplot(8,4,[9 10 13 14]) +imagesc(t,f,silog) +set(gca,'ydir','normal','clim',clim) +title('Interference spectrogram') +xlabel('Time [s]') +ylabel('Frequency [Hz]') +ch = colorbar; +ylabel(ch,'Magnitude [dB]') + +%% calculate and plot ideal masks + +% calculate ideal masks +[irm,ibm] = iosr.bss.idealMasks(st,si); + +% draw figures +subplot(8,4,[3 4 7 8]) +imagesc(t,f,irm) +set(gca,'ydir','normal','xticklabel',[],'yticklabel',[],'clim',[0 1]) +title('Ideal ratio mask (IRM)') +ch = colorbar; +ylabel(ch,'Mask value') +% +subplot(8,4,[11 12 15 16]) +imagesc(t,f,ibm) +set(gca,'ydir','normal','yticklabel',[],'clim',[0 1]) +title('Ideal binary mask (IBM)') +xlabel('Time [s]') +ch = colorbar; +ylabel(ch,'Mask value') + +%% resynthesise and plot output + +% calculate and apply ideal masks in one step +[z_irm,z_ibm,t] = iosr.bss.applyIdealMasks(xt,xi,win,hop,Fs); + +% draw figures +subplot(8,4,21:24) +plot(t,xt) +set(gca,'xticklabel',[],'xlim',[0 max(t)],'ylim',[-1 1]) +title('Clean target signal') +ylabel('Amplitude') +% +subplot(8,4,25:28) +plot(t,z_irm) +set(gca,'xticklabel',[],'xlim',[0 max(t)],'ylim',[-1 1]) +title('Target resynthesised from IRM') +ylabel('Amplitude') +% +subplot(8,4,29:32) +plot(t,z_ibm) +set(gca,'xlim',[0 max(t)],'ylim',[-1 1]) +title('Target resynthesised from IBM') +xlabel('Time [s]') +ylabel('Amplitude') diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/generateMixtures.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/generateMixtures.m new file mode 100644 index 0000000000000000000000000000000000000000..73011539c5ad9611dc992e2c00ba4bf3f1c59d1b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/generateMixtures.m @@ -0,0 +1,308 @@ +function mixtures = generateMixtures(targets,interferers,varargin) +%GENERATEMIXTURES Generate arrays of mixtures from targets and interferers. +% +% MIXTURES = IOSR.BSS.GENERATEMIXTURES(TARGETS,INTERFERERS) generates an +% array of MIXTURE objects using SOURCE objects TARGETS and INTERFERERS. +% Each mixture object contains one target element and SIZE(INTERFERERS,2) +% interferers (i.e. as many interferers as there are columns). How the +% inputs are combined is determined by the nature of the input or the +% 'COMBINE' setting (see below). +% +% MIXTURES = IOSR.BSS.GENERATEMIXTURES(...,'PARAMETER',VALUE) allows +% additional options to be specified. The options are listed below ({} +% indicate defaults). +% +% Independent variables +% +% 'azimuths' : {zeros([1 size(interferers,2)+1])} | array +% Specify the azimuths for the sources. The numeric array should +% have one more column than INTERFERERS. The first column is the +% target azimuth; subsequent columns are assigned to the +% interferer sources such that the Nth azimuth is assigned to the +% N-1th interferer column (N>1). Specifying this parameter will +% overwrite the source property. +% 'elevations' : {zeros([1 size(interferers,2)+1])} | array +% Specify the elevations for the sources. The specification is +% the same as for azimuths. +% 'sofa_paths' : {[]} | str | cellstr +% Specify the SOFA file(s) for the mixtures as one or more paths +% to SOFA files that are convolved with sources. The parameter +% should be a character array or cell array of strings. +% 'tirs' : {0} | scalar +% Specify the target-to-interferer ratios for the mixtures. +% +% TARGETS and INTERFERERS are also considered independent variables. +% +% Settings +% +% 'cache' : {false} | true +% Specify whether mixtures are cached as audio files, rather than +% being rendered ono-the-fly. The setting invokes +% mixture.write(). Files are named 'mixture-NNNN.wav' where NNNN +% is a counter padded with leading zeros. Target and interferer +% signals are also cached. +% 'combine' : 'all' | 'rows' +% Determines how the inputs are combined. If the independent +% variables have the same number of rows (ignoring empty or +% scalar variables) then the variables are combined on a +% row-by-row basis, with scalar variables applied to each row. +% This is the 'rows' option, which is the default when the above +% conditions apply; the conditions must be met in order to +% combine variables in this way. Alternatively, variables are +% combined in all combinations. This is the 'all' option, which +% is the default when variables have rows of different lengths; +% variables may each have any number of rows. +% 'decomposition' : {'stft'} | 'gammatone' +% The time-frequency decomposition used by the mixture. +% 'folder' : {'mixture_temp'} | str +% Specify a folder for storing cached audio files. +% 'fs' : {16000} | scalar +% Sampling frequency for the mixtures. +% +% See also IOSR.BSS.MIXTURE, IOSR.BSS.SOURCE, SOFALOAD. + +% Copyright 2016 University of Surrey. + + %% get input + + IVs = struct(... + 'azimuths',zeros([1 size(interferers,2)+1]),... + 'elevations',zeros([1 size(interferers,2)+1]),... + 'sofa_paths',[],... + 'tirs',0); + + settings = struct(... + 'fs',16000,... + 'cache',false,... + 'combine',[],... + 'folder','mixture_temp',... + 'decomposition','stft',... + 'stft',[],... + 'gammatone',[]); + + validOptions = [fieldnames(IVs); fieldnames(settings)]; + + %% check input + + % overwrite the default settings + IVs = overwrite(IVs,validOptions,varargin); + settings = overwrite(settings,validOptions,varargin); + + % decomposition settings + if isempty(settings.stft) + settings.stft = struct('win',1024','hop',512); + end + if isempty(settings.gammatone) + settings.gammatone = struct('cfs',iosr.auditory.makeErbCFs(20, settings.fs/2, 64),... + 'frame',round(0.01*settings.fs)); + end + + % check IVs + assert(isa(targets,'iosr.bss.source'), 'iosr:generateMixtures:invalidTargets', '''TARGETS'' must be of type iosr.bss.source') + assert(isa(interferers,'iosr.bss.source'), 'iosr:generateMixtures:invalidInterferers', '''INTERFERERS'' must be of type iosr.bss.source') + assert(isnumeric(IVs.azimuths), 'iosr:generateMixtures:invalidAzimuths', '''AZIMUTHS'' must be numeric') + assert(size(IVs.azimuths,2)==size(interferers,2)+1, 'iosr:generateMixtures:invalidAzimuths', '''AZIMUTHS'' should have one more column than INTERFERERS') + assert(isnumeric(IVs.elevations), 'iosr:generateMixtures:invalidElevations', '''ELEVATIONS'' must be numeric') + assert(size(IVs.elevations,2)==size(interferers,2)+1, 'iosr:generateMixtures:invalidElevations', '''ELEVATIONS'' should have one more column than INTERFERERS') + if ~isempty(IVs.sofa_paths) + if ischar(IVs.sofa_paths) + IVs.sofa_paths = cellstr(IVs.sofa_paths); + elseif ~iscellstr(IVs.sofa_paths) + error('iosr:generateMixtures:pathInvalid','sofa_paths should be a char array or cell array of strings') + end + end + + % check settings + assert(islogical(settings.cache), 'iosr:generateMixtures:invalidCache', '''CACHE'' must be logical') + assert(ischar(settings.folder), 'iosr:generateMixtures:invalidFolder', '''FOLDER'' must be a char array') + if ~isempty(settings.combine) + assert(ischar(settings.combine), 'iosr:generateMixtures:invalidCombine', '''COMBINE'' must be a char array') + end + assert(isnumeric(settings.fs) && isscalar(settings.fs), 'iosr:generateMixtures:invalidFs', '''FS'' must be a numeric scalar') + + % ensure column vectors + IVs.sofa_paths = IVs.sofa_paths(:); + IVs.tirs = IVs.tirs(:); + targets = targets(:); + + % append targets and interferers to IVs + IVs.targets = targets; + IVs.interferers = interferers; + + %% make mixtures + + % check if vars have equal number of rows (ignore scalar of empty) + [equal,iterations] = check_vars_equal_rows(IVs); + + % automatically determine combine method + if isempty(settings.combine) + if equal + settings.combine = 'rows'; + else + settings.combine = 'all'; + end + end + + var_size = vars_rows(IVs); + + % do some things according to combine mode + switch lower(settings.combine) + case 'all' + iterations = prod(max(var_size,1)); % recalculate if rows were equal + IV_size = [... + max(numel(IVs.targets),1),... + max(size(IVs.interferers,1),1),... + max(numel(IVs.sofa_paths),1),... + max(numel(IVs.tirs),1),... + max(size(IVs.azimuths,1),1),... + max(size(IVs.elevations,1),1)]; + case 'rows' + assert(equal, 'iosr:generateMixtures:rowsInvalidInput', 'Properties must have an equal number of rows if specifying ''COMBINE'' mode ''ROWS''') + otherwise + error('iosr:generateMixtures:unknownCombine','Unknown ''COMBINE'' property') + end + + % create the mixtures + if settings.cache + disp('Writing wav files.') + end + mixtures(iterations,1) = iosr.bss.mixture; % preallocate + for m = 1:iterations + switch lower(settings.combine) + % get settings for current iteration + case 'rows' + % read rows together + target = copy(getIV('targets',m)); + interferer = copy(getIV('interferers',m)); + sofa_path = getIV('sofa_paths',m); + tir = getIV('tirs',m); + azimuths = getIV('azimuths',m); + elevations = getIV('elevations',m); + case 'all' + % work through each variable separately + [n,p,q,r,s,t] = ind2sub(IV_size,m); + target = copy(getIV('targets',n)); + interferer = copy(getIV('interferers',p)); + sofa_path = getIV('sofa_paths',q); + tir = getIV('tirs',r); + azimuths = getIV('azimuths',s); + elevations = getIV('elevations',t); + end + % apply spatial settings to sources + target.azimuth = azimuths(1); + target.elevation = elevations(1); + for i = 1:length(interferer) + interferer(i).azimuth = azimuths(i+1); + interferer(i).elevation = elevations(i+1); + end + % calculate mixtures + mixtures(m,1) = iosr.bss.mixture(... + target,... + interferer,... + 'tir',tir,... + 'sofa_path',sofa_path,... + 'fs',settings.fs,... + 'decomposition',settings.decomposition,... + 'gammatone',settings.gammatone,... + 'stft',settings.stft); + if settings.cache + mixtures(m,1).write([settings.folder filesep sprintf('mixture-%05d.wav',m)]) + end + end + if settings.cache + disp('Done.') + end + + function val = getIV(field,row) + %GETIV retrieve independent variable + + % function to index into the option field + index = @(n,F) mod(n-1,size(F,1))+1; + + % return data + if isempty(IVs.(field)) % return empty + val = []; + else % return value + if ~iscellstr(IVs.(field)) + M = index(row,IVs.(field)); + val = IVs.(field)(M,:); + else + M = index(row,IVs.(field)(:)); + val = IVs.(field){M}; + end + end + + end + +end + +function opts = overwrite(opts,validOptions,vgin) +%OVERWRITE overwrite the default properties with varargin + + % count arguments + nArgs = length(vgin); + if round(nArgs/2)~=nArgs/2 + error('iosr:generateMixtures:nameValuePair','generateMixtures needs propertyName/propertyValue pairs') + end + optionNames = fieldnames(opts); + % overwrite defults + for pair = reshape(vgin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + opts.(optionNames{IX}) = pair{2}; + else + if ~any(strcmpi(pair{1},validOptions)) + error('iosr:generateMixtures:unknownOption',['''' pair{1} ''' is not a valid option']) + end + end + end +end + +function [equal,num] = check_vars_equal_rows(varargin) +%CHECK_VARS_EQUAL_ROWS check variables have the same number of elements +% +% CHECK_VARS_EQUAL_ROWS(A,B,C,...) and CHECK_VARS_EQUAL_ROWS(OPTS) checks +% the variables A, B, C, ..., or the structure OPTS, to test whether the +% variables/fields have the same number of elements. Scalar or empty +% variables/fields are ignored. + + % get number of elements in each variable/field + nums = max(vars_rows(varargin{:}),1); + + % determine equality + nums = nums(nums>1); + + if ~isempty(nums) + equal = all(nums==nums(1)); % determine equality + % return number of elements + if equal + num = nums(1); + else + num = prod(nums); + end + else + % one row + equal = true; + num = 1; + end + +end + +function num = vars_rows(varargin) +%VARS_ROWS return the number of rows in each variable +% +% VARS_ROWS(A,B,C,...) and VARS_ROWS(OPTS) returns the number of rows in +% variables A, B, C, ..., or the fields of structure OPTS. + + % convert struct to cell array + if isstruct(varargin{1}) && length(varargin)==1 + vgin = struct2cell(varargin{1}); + else + vgin = varargin; + end + + % return number of elements + num = cellfun(@(x) size(x,1),vgin); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/getFullMask.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/getFullMask.m new file mode 100644 index 0000000000000000000000000000000000000000..756b5815c40c0282ac7e87562f6c1a4d99562efb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/getFullMask.m @@ -0,0 +1,58 @@ +function m_full = getFullMask(m,frame_d,delay,kernel) +%GETFULLMASK Convert frame rate mask to a sample-by-sample mask +% +% M_FULL = IOSR.BSS.GETFULLMASK(M,FRAME_D) expands the time-frequency +% mask M, which has one unit for each frequency channel and frame of +% length FRAME_D (in samples), to a sample-by-sample mask. The mask M is +% a time-frequency mask, with one column for each frequency channel, and +% one row for each time frame. The resulting mask will have dimensions +% [FRAME_D*size(M,1) size(M,2)]. +% +% M_FULL = IOSR.BSS.GETFULLMASK(M,FRAME_D,DELAY) removes a delay from +% each frequency channel in the mask. DELAY is a vector, with the same +% number of elements as M has columns, containing a delay (in samples) +% that is removed from the corresponding frequency channel. The mask is +% subsequently zero-padded. +% +% M_FULL = IOSR.BSS.GETFULLMASK(M,FRAME_D,DELAY,KERNEL) allows smoothing +% to be applied to the full mask. By default, the full mask contains +% rectangular transitions at unit boundaries. Specifying KERNEL allows +% the transitions to be smoother, by convolving the full mask with a +% two-dimensional kernel (dimensions [frequency time]). The central part +% of the convolution is returned, so the centre of the KERNEL should be +% in the centre of the matrix. The kernel is normalised in order to +% ensure zero gain at DC. +% +% See also IOSR.BSS.RESYNTHESISE. + +% Copyright 2016 University of Surrey. + + + if nargin < 2 + error('iosr:getFullMask:nargin','Not enough input arguments') + end + + numchans = size(m,2); + frameCount = size(m,1); + + if nargin < 3 + delay = zeros(1,numchans); + end + if nargin < 4 + kernel = 1; + end + + % Create the sample-by-sample mask + m_full = zeros(frameCount*frame_d,numchans); + for i = 1:numchans + for j = 1:frameCount + m_full(((j-1)*frame_d+1):((j-1)*frame_d+1)+frame_d-1,i) = m(j,i); + end + m_full(:,i) = [m_full(delay(i)+1:end,i); zeros(delay(i),1)]; + end + + % convolve with kernel + kernel = kernel./sum(abs(kernel(:))); + m_full = conv2(m_full,kernel,'same'); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/idealMasks.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/idealMasks.m new file mode 100644 index 0000000000000000000000000000000000000000..0c9ac66f69c1a03c432fc40ae9d8e546e22cd238 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/idealMasks.m @@ -0,0 +1,61 @@ +function [irm,ibm] = idealMasks(st,si,q,a) +%IDEALMASKS Calculate ideal time-frequency masks from STFTs +% +% IRM = IOSR.BSS.IDEALMASKS(ST,SI) calculates the ideal ratio mask (IRM) +% using target STFT ST and interferer STFT SI. ST and SI must be the same +% size; IRM is the same size as ST and SI. +% +% [IRM,IBM] = IOSR.BSS.IDEALMASKS(...) returns the ideal binary mask +% (IBM). +% +% IRM = IOSR.BSS.IDEALMASKS(ST,SI,Q) uses the exponent Q to create an +% ideal sigmoidal mask by raising each of the time-frequency powers to Q. +% With Q=1 (default) the mask is the IRM. As Q->Inf the IRM will tend +% towards a binary mask. As Q->0 the mask will tend towards 0.5. +% +% [IRM,IBM] = IOSR.BSS.IDEALMASKS(ST,SI,Q,A) uses the threshold A to +% calculate the IBM. The threshold is in terms of the ratio of time +% frequency powers. With A=1 (default), the IBM is 1 when the target +% power is greater than the interferer power. Setting A=2, for example, +% requires the target power to be 6dB greater than the interference +% power. +% +% See also IOSR.BSS.APPLYMASK, IOSR.BSS.APPLYIDEALMASKS. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(isequal(size(st),size(si)), 'iosr:idealMasks:invalidInputs', 'ST and SI must be the same size') + + % check sigmoid + if nargin<3 + q = 1; + else + assert(isscalar(a), 'iosr:idealMasks:invalidQ', 'Q must be an scalar') + end + + % check threshold + if nargin<4 + a = 1; + else + assert(isscalar(a), 'iosr:idealMasks:invalidA', 'A must be an scalar') + end + + %% calculate masks + + % powers + St = abs(st).^2; + Si = abs(si).^2; + + % ideal ratio mask + irm = (St.^q)./((St.^q)+(Si.^q)); + irm(isnan(irm)) = 0; + + % ideal binary mask + if nargout>1 + ibm = +(St./Si>a); + ibm(isnan(ibm)) = 0; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/mixture.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/mixture.m new file mode 100644 index 0000000000000000000000000000000000000000..a32732f4af5a82088550c8fdd71df61c3d21956b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/mixture.m @@ -0,0 +1,1026 @@ +classdef mixture < iosr.dsp.audio +%MIXTURE Class of sound source separation mixture. +% +% iosr.bss.mixture objects contain information about a mixture of sound +% sources. +% +% IOSR.BSS.MIXTURE is a subclass of IOSR.DSP.AUDIO. +% +% IOSR.BSS.MIXTURE properties: +% azi_sep - The azimuthal separation of the widest sources +% (read-only) +% decomp - The result of the time-frequency decomposition +% (mixture) (read-only) +% decomp_i - The result of the time-frequency decomposition +% (interferer) (read-only) +% decomp_t - The result of the time-frequency decomposition +% (target) (read-only) +% decomposition - Set the time-frequency decomposition. The options +% are: +% 'stft' : short-time fourier transform +% (default) +% 'gammatone' : gammatone filterbank +% elevation - The median elevation of the mixture (read-only) +% filename_t - Name of the target audio file (based on the +% mixture filename) (read-only) +% filename_i - Name of the interferer audio file (based on the +% Mixture filename) (read-only) +% gammatone - Settings for the gammatone filterbank +% decomposition. The property is a structure +% containing the following fields: +% 'cfs' : the centre frequencies of the +% gammatone filterbank +% 'frame' : the frame length (in samples) +% sofa_path - Path to a SOFA file containing spatialisation data +% ibm - The ideal binary mask +% irm - The ideal ratio mask +% int_fns - A char array containing the filenames of all of +% the interfering sources (read-only) +% interferers - An array of interferer sources of type +% iosr.bss.source +% signal_t - The sampled data (target) (read-only) +% signal_i - The sampled data (interferer) (read-only) +% stft - Settings for the STFT decomposition. The property +% is a structure containing the following fields: +% 'hop' : the hop size of the STFT +% 'win' : the STFT window +% See iosr.dsp.stft for more information +% target - The target source of type iosr.bss.source +% tfPower - The (frame-based) time-frequency power (mixture) +% (read-only) +% tfPower_i - The (frame-based) time-frequency power +% (interferer) (read-only) +% tfPower_t - The (frame-based) time-frequency power (target) +% (read-only) +% tir - The target-to-interferer ratio (target or +% interferers are attenuated in order that their +% RMS amplitudes have this ratio) +% wdo - The w-disjoint orthogonality (read-only) +% wdo_lw - The loudness-weighted w-disjoint orthogonality +% (read-only) +% +% IOSR.BSS.MIXTURE methods: +% mixture - Create the mixture +% clearCache - Clears the internally cached data, reducing +% file size. +% copy - Create an independent copy of the mixture, its +% sources, and any rendered files +% applyMask - Apply a time-frequency mask +% deleteFiles - Delete the mixture audio files +% sound_t - Replay the target +% sound_i - Replay the interferer +% write - Save the mixture, target, and interferers to audio files +% Static methods: +% maskCentroids - Calculate the centroids of a time-frequency mask +% mixWdo - WDO of a mixture +% mixWdo_lw - Loudness-weighted WDO of a mixture +% mixWdo_Stokes - WDO calculated using Stokes's method +% +% Note that target and interferer properties may be modified as +% MIXTURE.TARGET.PROPERTY_NAME and MIXTURE.INTERFERERS(N).PROPERTY_NAME, +% except for the sampling frequency FS, which cannot be overridden. This +% ensures that the sampling frequencies are identical for the mixture and +% its sources. +% +% See also IOSR.DSP.AUDIO, IOSR.BSS.SOURCE, SOFALOAD, IOSR.DSP.STFT, +% IOSR.AUDITORY.GAMMATONEFAST. + +% Copyright 2016 University of Surrey. + +%TODO: Add more decompositions. + + properties (AbortSet) + decomposition = 'stft' % The time-frequency decomposition + gammatone = struct % Settings for the gammatone filterbank decomposition + sofa_path % Path to a SOFA file containing spatialisation data + stft = struct % Settings for the STFT decomposition + tir = 0 % The target to interferer ratio + interferers % An array of interferer sources of type iosr.bss.source + target % The target source of type iosr.bss.source + end + + properties (Dependent, SetAccess = protected) + signal % The sampled data (read-only) + end + + properties (Dependent, SetAccess = private) + azi_sep % The azimuthal separation of the widest sources (read-only) + decomp % The result of the time-frequency decomposition (mixture) (read-only) + decomp_i % The result of the time-frequency decomposition (interferer) (read-only) + decomp_t % The result of the time-frequency decomposition (target) (read-only) + elevation % The median elevation of the mixture (read-only) + filename_t % Name of the target audio file (read-only) + filename_i % Name of the interferer audio file (read-only) + ibm % Ideal binary mask (read-only) + irm % Ideal ratio mask (read-only) + int_fns % Filenames of all of the interfering sources (read-only) + numchans % Number of audio channels in the mixture (read-only) + signal_t % Return target (read-only) + signal_i % Return interferer (read-only) + tfPower % The time-frequency power (mixture) (read-only) + tfPower_i % The time-frequency power (interferer) (read-only) + tfPower_t % The time-frequency power (target) (read-only) + wdo % Return the w-disjoint orthogonality metric (read-only) + wdo_lw % Return the loudness-weighted w-disjoint orthogonality metric (read-only) + wdo_stokes % Return the w-disjoint orthogonality metric using Stokes's method (read-only) + end + + properties (Access = private) + cached_decomp % the cached mixture decomposition + decomp_cached = false % whether the mixture decomposition is cached + cached_decomp_i % the cached interferer decomposition + decomp_i_cached = false % whether the interferer decomposition is cached + cached_decomp_t % the cached target decomposition + decomp_t_cached = false % whether the target decomposition is cached + cached_tfPower % the cached mixture TF power + tfPower_cached = false % whether the mixture TF power is cached + cached_tfPower_i % the cached interferer TF power + tfPower_i_cached = false % whether the interferer TF power is cached + cached_tfPower_t % the cached target TF power + tfPower_t_cached = false % whether the target TF power is cached + end + + methods + + % constructor + function obj = mixture(target,interferers,varargin) + %MIXTURE Create a mixture + % + % OBJ = IOSR.BSS.MIXTURE(TARGET,INTERFERER) creates a mixture by + % summing together the target source and the interferer + % source(s). The sources are mixed together such that their RMS + % amplitudes are equal (target-to-interferer ratio is 0dB). The + % OBJ sampling rate is equal to the target sampling rate. + % Information about the sources' spatial location is ignored. + % + % OBJ = IOSR.BSS.MIXTURE(...,'PARAMETER',VALUE) allows additional + % options to be specified. The options are ({} indicate + % defaults): + % + % 'decomposition' : {'stft'} | 'gammatone' + % 'filename' : {[]} | str + % A filename used when writing the file with the write() + % method. The filename may also be set when calling the + % write() method. Filenames for the target and interferer + % are determined automatically, by append the filename + % with '_target' and '_interferer' respectively. + % 'fs' : {obj.target.fs} | scalar + % The sampling frequency of the mixture. All HRTFs and/or + % sources will be resampled to this frequency each time + % the signal is requested. + % 'gammatone' + % Settings for the gammatone filterbank + % decomposition. The property is a structure + % containing the following fields: + % 'cfs' : the centre frequencies of the gammatone + % filterbank (default is 64 channels + % equally spaced on the ERB scale between + % 20Hz and the Nyquist limit + % 'frame' : the frame length (in samples) (the + % default is 20ms) + % 'sofa_path' : {[]} | str + % A path to a SOFA file containing HRTFs that are + % convolved with sources in order to generate the + % mixture. + % 'stft' + % Settings for the STFT decomposition. The property + % is a structure containing the following fields: + % 'hop' : the hop size of the STFT (the default + % is 512) + % 'win' : the STFT window (the default is 1024) + % 'tir' : {0} | scalar + % The RMS ratio of the target and interfer sources. + % Interferer sources are individually set to this level + % prior to their summation. + % + % OBJ = IOSR.BSS.MIXTURE creates an empty mixture object with + % empty target and interferer sources. + % + % To speed up time-frequency operations, the IOSR.BSS.MIXTURE + % class caches time-frequency data internally, which can lead to + % large file sizes if the object is saved. Use the CLEARCACHE() + % method to empty the internal cache. + % + % Note that this is a handle class, as is IOSR.BSS.SOURCE. Target + % and interferer(s) are hence passed by reference. Use the COPY() + % method to create an independent copy of the mixture and its + % sources. + + if nargin > 0 + + assert(nargin>1, 'iosr:mixture:nargin', 'Not enough input arguments') + + propNames = {'filename','fs','sofa_path','tir','decomposition','stft','gammatone'}; + + % set sources + obj.target = target; + obj.interferers = interferers; + + % defaults + obj.fs = obj.target.fs; + obj.sofa_path = []; + obj.tir = 0; + obj.rendered = false; + + % default decomposition settings + obj.stft = struct('win',1024,'hop',512); + obj.gammatone = struct(... + 'cfs',iosr.auditory.makeErbCFs(20, obj.fs/2, 64),... + 'frame', round(0.01*obj.fs)... + ); + + % read parameter/value inputs + if nargin > 1 % if parameters are specified + obj.set_properties(varargin,propNames) + end + + % set sample rate to SOFA file if set and fs not specified + if ~isempty(obj.sofa_path) && all(~strcmp('fs',varargin)) + SOFAobj = SOFAload(obj.sofa_path); % load SOFA object + obj.fs = SOFAobj.Data.SamplingRate; + end + + % ensure fs for sources matches instance + obj.target.fs = obj.fs; + for n = 1:numel(obj.interferers) + obj.interferers(n).fs = obj.fs; + end + + % set parent + obj.target.parent = obj; + for n = 1:numel(obj.interferers) + obj.interferers(n).parent = obj; + end + + end + + end + + function z = applyMask(obj,m) + %APPLYMASK Apply a time-frequency mask to the mixture + % + % Z = IOSR.BSS.MIXTURE.APPLYMASK(M) applies the time-frequency + % mask M to the mixture. The mixture is transformed according to + % the objects decomposition settings. The transform is then + % multiplied with M. Lastly, the result is then inverse + % transformed (or reynthesised). The time-domain output Z is + % returned. + + switch lower(obj.decomposition) + case 'stft' + s = obj.decomp; + % correct dims + d = obj.stft_shifted_dims(s); + s = ipermute(s,d); + m = ipermute(m,d); + for c = 1:obj.numchans + % apply mask + z(:,c) = iosr.bss.applyMask( ... + s(:,:,c), ... + m(:,:,min(c,size(m,3))), ... + obj.stft.win, ... + obj.stft.hop, ... + obj.fs ... + ); %#ok<AGROW> + end + case 'gammatone' + x = obj.signal; + for c = 1:obj.numchans + z(:,c) = iosr.bss.resynthesise( ... + x(:,c), ... + obj.fs, ... + iosr.bss.cfs2fcs(obj.gammatone.cfs, obj.fs), ... + m(:,:,c), ... + 'frame_length', obj.gammatone.frame, ... + 'filter', 'sinc', ... + 'kernel', gausswin(obj.gammatone.frame) ... + ); %#ok<AGROW> + end + end + + z = obj.setlength(z,length(obj.signal)); + + end + + function sound_t(obj) + %SOUND_T Replay the target signal + % + % IOSR.BSS.MIXTURE.SOUND_T() replays the target signal. + + obj.replay(obj.signal_t) + + end + + function sound_i(obj) + %SOUND_I Replay the interferer signal + % + % IOSR.BSS.MIXTURE.SOUND_I() replays the interferer signal. + + obj.replay(obj.signal_i) + + end + + function write(obj,filename) + %WRITE Save the mixture to an audio file + % + % IOSR.BSS.MIXTURE.WRITE() writes the mixture to an audio file + % specified by MIXTURE.FILENAME, and also writes the target and + % interferer signals to automatically-determined file names + % (MIXTURE.FILENAME_T and MIXTURE.FILENAME_I respectively). + % + % IOSR.BSS.MIXTURE.WRITE(FILENAME) uses the specified FILENAME + % and updates MIXTURE.FILENAME. + + if exist('filename','var')==1 + fn = filename; + else + fn = obj.filename; + end + + if obj.rendered && exist(fn, 'file') == 2 + if strcmp(obj.filename,fn) + % nothing to do + else + copyfile(obj.filename,fn); + copyfile(obj.filename_t,obj.make_target_filename(fn)); + copyfile(obj.filename_i,obj.make_interferer_filename(fn)); + end + else + % check filename is valid + obj.filename = fn; + assert(ischar(obj.filename) && ~isempty(obj.filename),'iosr:mixture:invalidFilename','FILENAME must be a non-empty char array. Set filename as MIXTURE.FILENAME or MIXTURE.WRITE(FILENAME).') + + % normalize + M = obj.signal; + T = obj.signal_t; + I = obj.signal_i; + [~,gain] = obj.normalize([M T I]); + M = M.*gain; + T = T.*gain; + I = I.*gain; + + % ensure path + obj.ensure_path(obj.filename) + + % write audio files + audiowrite(obj.filename,M,obj.fs); + audiowrite(obj.filename_t,T,obj.fs); + audiowrite(obj.filename_i,I,obj.fs); + + % set flag to indicate mixture has been rendered to an audio file + obj.rendered = true; + + end + + end + + function deleteFiles(obj) + %DELETEFILES Delete the mixture audio files + + if exist(obj.filename, 'file') == 2 + delete(obj.filename); + end + if exist(obj.filename_t, 'file') == 2 + delete(obj.filename_t); + end + if exist(obj.filename_i, 'file') == 2 + delete(obj.filename_i); + end + obj.rendered = false; + + end + + function clearCache(obj) + %CLEARCACHE Clear the internal cache + + obj.updateCachedFalse(); + obj.cached_decomp = []; + obj.cached_decomp_i = []; + obj.cached_decomp_t = []; + obj.cached_tfPower = []; + obj.cached_tfPower_i = []; + obj.cached_tfPower_t = []; + end + + % set/validate properties + + % set decomposition + function set.decomposition(obj,val) + assert(any(strcmpi(val,{'stft','gammatone'})), 'iosr:mixture:invalidDecomposition', '''decomposition'' must be ''stft'' or ''gammatone'''); + obj.updateCachedFalse(); + obj.decomposition = val; + end + + % set gammatone settings + function set.gammatone(obj,val) + assert(isstruct(val), 'iosr:mixture:invalidGammatoneStruct', '''gammatone'' must be a struct') + assert(all(ismember(fieldnames(val)',{'cfs','frame'})), 'iosr:mixture:invalidGammatoneFields', 'gammatone structure must contain fields ''cfs'' and ''frame''') + obj.updateCachedFalse; + obj.gammatone = val; + end + + % set stft settings + function set.stft(obj,val) + assert(isstruct(val), 'iosr:mixture:invalidStftStruct', '''stft'' must be a struct') + assert(all(ismember(fieldnames(val)',{'win','hop'})), 'iosr:mixture:invalidStftFields', 'stft structure must contain fields ''win'' and ''hop''') + obj.updateCachedFalse; + obj.stft = val; + end + + % set tir + function set.tir(obj,val) + obj.tir = val; + obj.property_changed('tir',val); + end + + % validate sofa_path + function set.sofa_path(obj,val) + assert(ischar(val) || isempty(val), 'iosr:mixture:invalidSofaPath', 'sofa_path must be a char array or an empty array') + if ~isempty(val) + assert(exist(val,'file')==2, 'iosr:mixture:invalidSofaPath', 'SOFA file does not exist') + end + obj.sofa_path = val; + obj.property_changed('sofa_path',val); + end + + % validate interferers + function set.interferers(obj,val) + assert(isa(val,'iosr.bss.source'), 'iosr:mixture:invalidInterferers', 'INTERFERERS must be of type source') + obj.interferers = val; + obj.property_changed('interferers',val); + end + + % validate target + function set.target(obj,val) + assert(isa(val,'iosr.bss.source') && numel(val)==1, 'iosr:mixture:invalidTarget', 'TARGET must be a scalar of type source') + obj.target = val; + obj.property_changed('target',val); + end + + % dependent properties + + % get decomposition result (mixture) + function s = get.decomp(obj) + if obj.decomp_cached + s = obj.cached_decomp; + else + s = obj.decompose(obj.signal); + obj.cached_decomp = s; + obj.decomp_cached = true; + end + end + + % get decomposition result (interferer) + function s = get.decomp_i(obj) + if obj.decomp_i_cached + s = obj.cached_decomp_i; + else + s = obj.decompose(obj.signal_i); + obj.cached_decomp_i = s; + obj.decomp_i_cached = true; + end + end + + % get decomposition result (target) + function s = get.decomp_t(obj) + if obj.decomp_t_cached + s = obj.cached_decomp_t; + else + s = obj.decompose(obj.signal_t); + obj.cached_decomp_t = s; + obj.decomp_t_cached = true; + end + end + + % get azimuthal separation + function s = get.azi_sep(obj) + [s,~] = get_loc(obj); + end + + % get median elevation + function e = get.elevation(obj) + [~,e] = get_loc(obj); + end + + % target filename + function fn = get.filename_t(obj) + fn = obj.make_target_filename(obj.filename); + end + + % interferer filename + function fn = get.filename_i(obj) + fn = obj.make_interferer_filename(obj.filename); + end + + % ibm + function m = get.ibm(obj) + switch lower(obj.decomposition) + case 'stft' + for c = 1:obj.numchans + [~,m(:,:,c)] = iosr.bss.idealMasks( ... + obj.decomp_t(:,:,c), ... + obj.decomp_i(:,:,c) ... + ); %#ok<AGROW> + end + case 'gammatone' + T = obj.tfPower_t; + I = obj.tfPower_i; + m = +(T>I); + end + end + + % irm + function m = get.irm(obj) + switch lower(obj.decomposition) + case 'stft' + for c = 1:obj.numchans + m(:,:,c) = iosr.bss.idealMasks( ... + obj.decomp_t(:,:,c), ... + obj.decomp_i(:,:,c) ... + ); %#ok<AGROW> + end + case 'gammatone' + T = obj.tfPower_t; + I = obj.tfPower_i; + m = T./(T+I); + end + m(isnan(m) | isinf(m)) = 0; + end + + % filenames of all interferers + function fns = get.int_fns(obj) + for n = 1:length(obj.interferers) + if n==1 + fns = obj.interferers(n).filename; + else + fns = [fns ', ' obj.interferers(n).filename]; %#ok<AGROW> + end + end + end + + % number of audio channels + function n = get.numchans(obj) + if obj.hrtf_is_set() + s = SOFAload(obj.sofa_path); + n = size(s.Data.IR,2); + else + iN = [obj.interferers.numchans]; + n = max([obj.target.numchans; iN(:)]); + end + end + + % return target signal + function signal_t = get.signal_t(obj) + if obj.rendered && exist(obj.filename_t,'file')==2 % don't bother calculating + signal_t = audioread(obj.filename_t); + else % calculate + signal_t = return_source(obj,obj.target); + if obj.tir<0 + % attenuate according to TIR + Trms = iosr.dsp.rms(signal_t(:)); + Irms = iosr.dsp.rms(obj.signal_i(:)); + signal_t = signal_t./(Trms/Irms); % match to interferer + signal_t = signal_t.*(10^(obj.tir/20)); % attenuate + end + end + end + + % return interferer signal + function signal_i = get.signal_i(obj) + if obj.rendered && exist(obj.filename_i,'file')==2 % don't bother calculating + signal_i = audioread(obj.filename_i); + else % calculate + signal_i = zeros(1, obj.numchans); % initialise + maxlength = 0; % initialise + for n = 1:numel(obj.interferers) % step through each interferer + % source signal (ensure 2-channel) + s = obj.return_source(obj.interferers(n)); + % ensure signals are same length, or zero-pad + maxlength = max([length(s) maxlength]); + s = obj.setlength(s,maxlength); + signal_i = obj.setlength(signal_i,maxlength); + % add source to interferer + signal_i = signal_i + s; + end + if obj.tir>=0 + % attenuate according to TIR + Trms = iosr.dsp.rms(obj.signal_t(:)); + Irms = iosr.dsp.rms(signal_i(:)); + signal_i = signal_i./(Irms/Trms); % match to interferer + signal_i = signal_i./(10^(obj.tir/20)); % attenuate + end + end + end + + % return mixture signal + function signal = get.signal(obj) + if obj.rendered && exist(obj.filename,'file')==2 % don't bother calculating + signal = audioread(obj.filename); + else % calculate + % return target and interferers + T = obj.signal_t; + I = obj.signal_i; + % mix, ensuring equal length + maxlength = max([length(T) length(I)]); + signal = obj.setlength(T,maxlength) + obj.setlength(I,maxlength); + end + end + + % return time-frequency power (mixture) + function val = get.tfPower(obj) + if obj.tfPower_cached + val = obj.cached_tfPower; + else + val = obj.tf_power(obj.decomp); + obj.cached_tfPower = val; + obj.tfPower_cached = true; + end + end + + % return time-frequency power (interferer) + function val = get.tfPower_i(obj) + if obj.tfPower_i_cached + val = obj.cached_tfPower_i; + else + val = obj.tf_power(obj.decomp_i); + obj.cached_tfPower_i = val; + obj.tfPower_i_cached = true; + end + end + + % return time-frequency power (target) + function val = get.tfPower_t(obj) + if obj.tfPower_t_cached + val = obj.cached_tfPower_t; + else + val = obj.tf_power(obj.decomp_t); + obj.cached_tfPower_t = val; + obj.tfPower_t_cached = true; + end + end + + % return wdo + function w = get.wdo(obj) + w = obj.mixWdo(abs(obj.decomp_t), abs(obj.decomp_i)); + end + + % return loudness-weighted wdo + function w = get.wdo_lw(obj) + [S,f] = obj.decompose(obj.signal_t); + w = obj.mixWdo_lw(abs(S), abs(obj.decomp_i), f); + end + + % return Stokes's wdo + function w = get.wdo_stokes(obj) + w = obj.mixWdo_Stokes(obj.irm); + end + + end + + methods (Static, Access = public) + + function [C, Ct, Cf] = maskCentroids(m, fs, decomposition, nfft, hop) + %MASKCENTROIDS Return various time-frequency mask centroids + % + % C = IOSR.BSS.MIXTURE.MASKCENTROIDS(M,FS,NFFT,HOP) returns the + % time-frequency mask centroid C calculated from mask M, sample + % rate FS, FFT-length NFFT, and and hop size HOP. The mask + % centroid is a unitless measure of the centroid of a + % time-frequency mask. The mask centroid is a measure of the + % frequency content of a time-frequency mask. + % + % [C,Ct,Cf] = IOSR.BSS.MIXTURE.MASKCENTROIDS(...) returns the + % time-related spectral centroid (in Hz) Ct and the + % frequency-related spectral centroid (in seconds) Cf. + + assert(ischar(decomposition), 'iosr:mixture:invalidDecomposition', '''decomposition'' must be a char array') + + numchans = size(m,3); + frame_frequency = fs/hop; + switch lower(decomposition) + case 'stft' + assert(isscalar(nfft), 'iosr:mixture:invalidNfft', '''nfft'' must be a scalar') + quefrency = fs/nfft; + case 'gammatone' + assert(isvector(nfft), 'iosr:mixture:invalidNfft', '''cfs'' must be a scalar') + cfs = nfft; + quefrency = fs/min(diff(iosr.auditory.erbRate2hz(cfs))); + otherwise + error('iosr:mixture:unknownDecomp','Unknown decomposition.') + end + + f_dct = repmat((((0:size(m,1)-1)./size(m,1)).*frame_frequency)',1,size(m,2)); + c_dct = repmat(((0:size(m,2)-1)./size(m,2)).*quefrency,size(m,1),1); + + C = zeros(1, numchans); + Ct = zeros(1, numchans); + Cf = zeros(1, numchans); + for c = 1:numchans + X = abs(dct(m(:,:,c))); + sumX = sum(sum(X)); + C(c) = sum(sum(X.*f_dct.*c_dct))./sumX; + Ct(c) = sum(sum(X.*f_dct))./sumX; + Cf(c) = sum(sum(X.*c_dct))./sumX; + end + + end + + function w = mixWdo(st, si) + %MIXWDO Calculate the mixture w-disjoint orthogonality + % + % W = IOSR.BSS.MIXTURE.MIXWDO(St,Si) calculates the w-disjoint + % orthogonality of a target and interferer(s) from their + % time-frequency magnitudes St and Si. The w-disjoint + % orthogonality is estimated by the two-dimensional + % cross-correlation coefficient of the source magnitudes. + + numchans = size(st,3); + w = zeros(1,numchans); + for c = 1:numchans + w(c) = corr2(st(:,:,c),si(:,:,c)); + end + + end + + function w = mixWdo_lw(st, si, f) + %MIXWDO_LW Calculate the loudness-weighted w-disjoint orthogonality + % + % W = IOSR.BSS.MIXTURE.MIXWDO_LW(St,Si,F) calculates the + % loudness-weighted w-disjoint orthogonality of a target and + % interferer(s) from their time-frequency magnitudes St and Si. + % The weighting is calculated from the ISO-226 65-phon equal + % loudness contour using the frequency vector F containing the + % frequency of each bin of St and Si. The magnitudes are + % multiplied with the loudness-weighting factor prior to + % calculating the WDO. + % + % See also IOSR.AUDITORY.LOUDWEIGHT. + + lw = iosr.auditory.loudWeight(f(:), 65)'; + lw = repmat(lw,size(st,1),1,size(st,3)); + w = iosr.bss.mixture.mixWdo(st.*lw,si.*lw); + + end + + function w = mixWdo_Stokes(irm) + %MIXWDO_LW Calculate the w-disjoint orthogonality using Stokes's method + % + % W = IOSR.BSS.MIXTURE.MIXWDO_STOKES(IRM) calculates the + % w-disjoint orthogonality using Stokes's method [1]. The method + % utilizes the ideal ratio mask (IRM), which is 0.5 when the + % target and interferer have equal power, and tends towards 0 or + % 1 when either source dominates. + % + % References + % + % [1] Stokes, Tobias W. (2015) Improving the perceptual quality + % of single-channel blind audio source separation. Doctoral + % thesis, University of Surrey. + + h = hist(irm(:),11)./numel(irm); + hw = [0:0.2:1 0.8:-0.2:0]; + w = sum(h.*hw); + + end + + end + + methods (Static, Access = private) + + function y = setlength(x,signal_length) + %SETLENGTH Crop or zero-pad signal to specified length + + d = size(x); + if size(x,1)>signal_length % need to crop + subsidx = [{1:signal_length} repmat({':'},1,ndims(x)-1)]; + y = x(subsidx{:}); + elseif size(x,1)<signal_length % need to zero-pad + y = [x; zeros([signal_length-size(x,1),d(2:end)])]; + else % do nothing + y = x; + end + + end + + function fn = append_filename(filename,append) + %APPEND_FILENAME Append strings to MIXTURE.FILENAME + + if isempty(filename) % do nothing if filename is empty + fn = []; + else % append + [filepath,name,ext] = fileparts(filename); % break up filename + newname = [name append ext]; % append + if isempty(filepath) % only filename specified + fn = newname; + else % path specified + fn = [filepath filesep newname]; + end + end + + end + + function d = stft_shifted_dims(s) + %STFT_SHIFTED_DIMS Dim order for STFT, swapping time and bins + + dim_order = 1:ndims(s); + if ndims(s) > 2 %#ok<ISMAT> + d = dim_order([2 1 dim_order(3:end)]); + else + d = [2 1]; + end + end + + end + + methods (Access = private) + + function c = hrtf_is_set(obj) + %HRTF_IS_SET Determine whether HRTFs are specified + + c = ~isempty(obj.sofa_path); + + end + + function s = return_source(obj,src) + %RETURN_SOURCE Return signal from specified source + + % ensure correct channel count + if ~src.precomposed && obj.hrtf_is_set() + src.numchans = 1; % signal will be spatialised + else + src.numchans = obj.numchans; % signal will be mixed directly + end + x = src.signal; + % return/convolve signal + if ~src.precomposed && obj.hrtf_is_set() % convolve + s = obj.spat(obj.sofa_path,x,src.azimuth,src.elevation,obj.fs); + else % return directly + s = x; + end + + end + + function [s,em] = get_loc(obj) + %GET_LOC Return location information + + % get angles from the sources + a = zeros(numel(obj.interferers)+1,1); + e = a; + for n = 1:numel(obj.interferers) + a(n) = obj.interferers(n).azimuth; + e(n) = obj.interferers(n).elevation; + end + a(end) = obj.target.azimuth; + e(end) = obj.target.elevation; + + % get separation + if any(a<0) % assume angles are -179:180 + s = abs(max(a)-min(a)); + else % assume angles are 0:359 + s = (360-max(a))+min(a); + end + s = mod(s,180); + + % get elevation + em = median(e); + + end + + function fn = make_target_filename(obj,filename) + %MAKE_TARGET_FILENAME Return the automated target filename + + fn = obj.append_filename(filename,'_target'); + + end + + function fn = make_interferer_filename(obj,filename) + %MAKE_INTERFERER_FILENAME Return the automated interferer filename + + fn = obj.append_filename(filename,'_interferer'); + + end + + function [s,f,t] = decompose(obj,x) + %DECOMPOSE Transform a signal into the time-frequency domain + + switch lower(obj.decomposition) + case 'stft' + for c = 1:obj.numchans + [s(:,:,c),f,t] = iosr.dsp.stft(x(:,c), obj.stft.win, obj.stft.hop, obj.fs); %#ok<AGROW> + end + % put time down column + s = permute(s,obj.stft_shifted_dims(s)); + s = obj.setlength(s, obj.get_frame_count(length(obj.signal))); + case 'gammatone' + f = obj.gammatone.cfs; + t = (0:length(x)-1)./obj.fs; + for c = 1:obj.numchans + s(:,:,c) = iosr.auditory.gammatoneFast(x(:,c), obj.gammatone.cfs, obj.fs); %#ok<AGROW> + end + end + + end + + function y = tf_power(obj,x) + %TF_POWER Calculate TF power. + + switch lower(obj.decomposition) + case 'gammatone' + frame_count = obj.get_frame_count(size(x,1)); + y = zeros(frame_count,length(obj.gammatone.cfs),obj.numchans); + for m = 1:frame_count + samples = (m-1)*obj.gammatone.frame+1:m*obj.gammatone.frame; + for N = 1:size(x,3) + y(m,:,N) = sum(x(samples,:,N).^2); + end + end + case 'stft' + y = abs(x).^2; + end + + end + + function frame_count = get_frame_count(obj, signal_length) + %GET_FRAME_COUNT Calculate number of T-F frames. + + assert(isscalar(signal_length), 'iosr:mixture:invalidSignalLength', 'SIGNAL_LENGTH must be a scalar.') + + switch lower(obj.decomposition) + case 'gammatone' + frame_count = floor(signal_length/obj.gammatone.frame); + case 'stft' + frame_count = fix((signal_length-(obj.nfft-obj.stft.hop))/obj.stft.hop); + end + + end + + function n = nfft(obj) + %NFFT return the fft length + + if isscalar(obj.stft.win) + n = obj.stft.win; + else + n = length(obj.stft.win); + end + end + + function updateCachedFalse(obj) + obj.decomp_cached = false; + obj.decomp_i_cached = false; + obj.decomp_t_cached = false; + obj.tfPower_cached = false; + obj.tfPower_i_cached = false; + obj.tfPower_t_cached = false; + end + + end + + methods(Access = protected) + + function property_changed(obj,name,val) + %PROPERTY_CHANGED handle property changes + + obj.rendered = false; + obj.updateCachedFalse(); + + switch lower(name) + case 'fs' + obj.target.fs = val; + for n = 1:numel(obj.interferers) + obj.interferers(n).fs = val; + end + end + + end + + function cpObj = copyElement(obj) + %COPYELEMENT Overload copy method with additional functionality + + % Make a shallow copy of all properties + cpObj = copyElement@iosr.dsp.audio(obj); + + % Changed rendered file name + cpObj.filename = obj.append_filename(cpObj.filename,'_copy'); + + % copy files + if obj.rendered + if exist(obj.filename,'file')==2 + copyfile(obj.filename,cpObj.filename) + end + if exist(obj.filename_i,'file')==2 + copyfile(obj.filename_i,cpObj.filename_i) + end + if exist(obj.filename_t,'file')==2 + copyfile(obj.filename_t,cpObj.filename_t) + end + end + + % Make a deep copy of target and interferers + cpObj.target = copy(obj.target); + cpObj.interferers = copy(obj.interferers); + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/resynthesise.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/resynthesise.m new file mode 100644 index 0000000000000000000000000000000000000000..6fb2d521b2d5810e613f682f42f74e662256dc7c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/resynthesise.m @@ -0,0 +1,152 @@ +function output = resynthesise(x,fs,cfs,m,varargin) +%RESYNTHESISE Resynthesise a target from a time-frequency mask +% +% OUTPUT = IOSR.BSS.RESYNTHESISE(X,FS,CFS,M) takes an input vector X, +% sampled at FS Hz, and applies the time-frequency mask M. The mask M is +% a matrix, with one column for each frequency channel, and one row for +% each sample. A row may also correspond to a frame - see 'frame_length' +% option below. The centre frequency of each column is contained in CFS. +% +% OUTPUT = IOSR.BSS.RESYNTHESISE(X,FS,CFS,M,'PARAMETER',VALUE) allows a +% number of options to be specified. The options are: +% +% % ({} indicates the default value) +% +% 'frame_length' : {1} | scalar +% The frame length for each time-frequency unit in M, in samples. +% 'delay' : {zeros(size(m,2),1)} | vector +% The delay in the filterbank when the time-frequency mask M was +% calculated. The delay is removed only when 'frame_length' > 1 and +% the full mask must be reconstructed. The value should be a vector +% whose length is equal to the number of columns in M; delay(n) is +% the delay in frequency band cfs(n). The delay does not affect the +% ouput of the reconstruction filters, since the filters are +% zero-phase. +% 'kernel' : {1} | vector +% Allows smoothing to be applied to the full mask. See +% IOSR.BSS.GETFULLMASK for more details. +% 'filter' : {'gammatone'} | 'sinc' +% Allows the reconstruction filter to be specified. By default a +% gammatone filterbank is used, and cfs corresponds to the filter +% centre frequencies. Alternatively a series sinc band-pass filters +% can be used. In this case it is assumed that the frequencies in cfs +% correspond to the upper cut-off frequencies of the sinc filters. +% The function IOSR.BSS.CFS2FCS can be used to calculate the cut-off +% frequencies. +% 'order' : {fs} | scalar +% The sinc filter order. +% +% Algorithm +% +% The algorithm has the following steps: +% 1) If necessary, obtain the full (smoothed) binary mask. See +% IOSR.BSS.GETFULLMASK. +% 2) Pass the vector x through the reconstruction filterbank, with +% centre/cut-off frequencies cfs. +% 3) Multiply the full mask with the output of the filterbank. +% 4) Sum the responses of the filterbank to produce a vector the same +% size as x. +% +% See also IOSR.BSS.CFS2FCS, IOSR.BSS.GETFULLMASK, IOSR.BSS.SINCFILTER. + +% Copyright 2016 University of Surrey. + + %% parse input + + if nargin<4 + error('iosr:resynthesise:tooFewInputArgs','Not enough input arguments') + end + + numchans = size(m,2); + + options = struct(... + 'frame_length',1,... + 'delay',zeros(numchans,1),... + 'kernel',1,... + 'filter','gammatone',... + 'order',fs); + + % read parameter/value inputs + if nargin > 4 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:resynthesise:nameValuePairs','RESYNTHESISE needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:resynthesise:unknownParameter','%s is not a recognized parameter name',pair{1}) + end + end + end + + delay = options.delay; + kernel = options.kernel; + outfilter = options.filter; + frame_d = options.frame_length; + order = options.order; + + % validate + assert(isvector(x) && isnumeric(x), 'iosr:resynthesise:invalidX', 'x must be a vector.'); + assert(all(round(delay)==delay), 'iosr:resynthesise:invalidDelay', 'Values in ''delay'' must be integers.'); + assert(length(delay)==numchans && isnumeric(delay), 'iosr:resynthesise:invalidDelay', 'The ''delay'' parameter must be a numeric vector the same length as the number of columns in m.'); + assert(ischar(outfilter), 'iosr:resynthesise:invalidFilter', 'The ''filter'' option must be a char array (string).'); + assert(round(frame_d)==frame_d && isscalar(frame_d), 'iosr:resynthesise:invalidFrame', '''frame_length'' must be a integer scalar.'); + assert(isnumeric(kernel), 'iosr:resynthesise:invalidKernel', '''kernel'' must be numeric.'); + assert(isvector(cfs) && length(cfs)==numchans && isnumeric(cfs), 'iosr:resynthesise:invalidCfs', 'cfs must be a vector with the same number of elements as there are columns of m.') + + %% get sample-by-sample masks + + if frame_d>1 + m_full = iosr.bss.getFullMask(m,frame_d,delay,kernel); + else + m_full = m; + end + + % crop or zero-pad x to match mask + if size(m_full,1)<length(x) + xpad = x(1:length(m_full)); + elseif size(m_full,1)>length(x) + xpad = [x; zeros(size(m_full,1)-length(x),1)]; + else + xpad = x; + end + + %% Pass x through reconstruction filterbank + + switch lower(outfilter) + case 'gammatone' + z = iosr.auditory.gammatoneFast(xpad,cfs,fs,true); % phase aligned GTFB + case 'sinc' + fcs = [0 cfs]; + z = zeros(length(xpad),numchans); + for i = 1:numchans + z(:,i) = iosr.dsp.sincFilter(xpad,fcs(i:i+1)./(fs/2),order)'; + end + otherwise + error('Unknown ''filter'' option specified') + end + + %% create output + + % apply mask + z = z.*m_full; + + % Sum to create waveforms + output = sum(z,2); + + % crop or zero-pad output to match input + if length(output)>length(x) + output = output(1:length(x)); + elseif length(output)<length(x) + output = [output; zeros(length(x)-length(output),1)]; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/source.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/source.m new file mode 100644 index 0000000000000000000000000000000000000000..bdc440efa2efd095a3fd014683b4da2776bd74a5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+bss/source.m @@ -0,0 +1,224 @@ +classdef source < iosr.dsp.audio +%SOURCE Class of sound source separation source. +% +% iosr.bss.source objects contain information about a sound source +% (including its spatial location). iosr.bss.source objects are passed to +% iosr.bss.mixture objects in order to create a mixture. +% +% IOSR.BSS.SOURCE is a subclass of IOSR.DSP.AUDIO. +% +% IOSR.BSS.SOURCE properties: +% azimuth - Azimuth of the source +% elevation - Elevation of the source +% numchans - Number of audio channels in the source +% precomposed - Logical flag indicating whether the source should be +% spatialised +% +% IOSR.BSS.SOURCE methods: +% source - Create a source object +% copy - Create an independent copy of the source (but not its +% audio file) +% write - Write the source audio file (and resample/downmix) +% +% See also IOSR.DSP.AUDIO, IOSR.BSS.MIXTURE. + +% Copyright 2016 University of Surrey. + + properties (AbortSet) + azimuth % Azimuth of the source + elevation % Elevation of the source + numchans % Number of audio channels in the source + precomposed % Logical flag indicating whether the source should be spatialised + end + + properties (Dependent, SetAccess = protected) + signal % The sampled data (read-only) + end + + properties (GetAccess = private, SetAccess = public) + parent + end + + methods + + % constructor + function obj = source(filename,varargin) + %SOURCE Create a source object + % + % OBJ = IOSR.BSS.SOURCE(FILENAME) creates a source whose signal + % is contained in the audio file FILENAME. The source will have + % an azimuth and elevation of 0. The number of channels and + % sampling frequency will be determined by the audio file. + % + % OBJ = IOSR.BSS.SOURCE(...,'PARAMETER',VALUE) allows additional + % options to be specified. The options are ({} indicate + % defaults): + % + % 'azimuth' : {0} | scalar + % The azimuth of the source for rendering. + % 'elevation' : {0} | scalar + % The elevation of the source for rendering. + % 'fs' : {fs of FILENAME} | scalar + % The sampling frequency of the source. If the sampling + % frequency of the audio file FILENAME does not match, + % the audio file will be resampled each time the signal + % is requested. + % 'precomposed' : {false} | true + % Logical flag indicating whether the source should be + % spatialised. By default it is assumed that the source + % is a point source (irrespective of its channel count), + % and it will be spatialised. When set to true, the + % source will be summed directly with the spatial signal. + % 'numchans' : {numchans of FILENAME} | scalar + % The number of channels in the source. If this does not + % match the channel count of the audio file FILENAME, the + % audio file will be up-/down-mixed each time the signal + % is requested. + % + % The FS and NUMCHANS parameters do not affect the underlying + % audio file, but are implemented on-the-fly each time the signal + % is requested. To render the changes to a new audio file, use + % the write() method. + % + % OBJ = IOSR.BSS.SOURCE creates an empty source object. + % + % Note that this is a handle class. Sources are hence passed by + % reference. Use the COPY() method to create an independent copy + % of the source. + % + % See also IOSR.DSP.AUDIO.UP_DOWN_MIX. + + if nargin > 0 + + propNames = {'azimuth','elevation','fs','precomposed','numchans'}; + + obj.filename = filename; + info = audioinfo(obj.filename); + + % defaults + obj.azimuth = 0; + obj.elevation = 0; + obj.precomposed = false; + obj.fs = info.SampleRate; + obj.numchans = info.NumChannels; + obj.rendered = false; + + % read parameter/value inputs + if nargin > 1 % if parameters are specified + obj.set_properties(varargin,propNames) + end + + end + + end + + function write(obj,filename) + %WRITE Write the source audio file (and resample/downmix) + % + % IOSR.BSS.SOURCE.WRITE() overwrites the source's audio file. If + % the source audio file's sampling rate and/or channel count do + % not match the object's properties, then the audio file will be + % resampled and/or up- or down-mixed accordingly. + % + % IOSR.BSS.SOURCE.WRITE(FILENAME) writes the audio file to the + % specified file FILENAME and updates SOURCE.FILENAME. + % + % See also IOSR.DSP.AUDIO.UP_DOWN_MIX. + + % overwrite filename if one is specified + if exist('filename','var')==1 + obj.filename = filename; + end + + assert(~isempty(obj.filename), 'iosr:source:invalidFile', 'SOURCE.FILENAME is empty.') + + % ensure path exists + obj.ensure_path(obj.filename) + + % write new file and update filename + audiowrite(obj.filename,obj.normalize(obj.signal),obj.fs); + obj.rendered = true; + + end + + % validate properties + + % validate azimuth + function set.azimuth(obj,val) + assert(isscalar(val), 'iosr:source:invalidAzimuth', 'AZIMUTH must be a scalar') + obj.azimuth = val; + obj.property_changed('azimuth',val); + end + + % validate elevation + function set.elevation(obj,val) + assert(isscalar(val), 'iosr:source:invalidElevation', 'ELEVATION must be a scalar') + obj.elevation = val; + obj.property_changed('elevation',val); + end + + % validate numchans + function set.numchans(obj,val) + assert(isscalar(val), 'iosr:source:invalidNumchans', 'NUMCHANS must be a scalar') + obj.numchans = val; + obj.property_changed('numchans',val); + end + + % validate precomposed + function set.precomposed(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:source:invalidPrecomposed', 'PRECOMPOSED property must be true or false') + obj.precomposed = val; + obj.property_changed('precomposed',val); + end + + % dependent properties + + % get dependent property signal + function signal = get.signal(obj) + + % read audio file + [signal,fs2] = audioread(obj.filename); + + % do more stuff if differences not rendered + if ~obj.rendered + N = size(signal,2); + + if fs2~=obj.fs % resample + signal = resample(signal,obj.fs,fs2); + end + if N~=obj.numchans % downmix + signal = iosr.dsp.audio.up_down_mix(signal,obj.numchans); + end + end + + end + + end + + methods(Access = protected) + + function property_changed(obj,name,val) + %PROPERTY_CHANGED handle property changes + + obj.rendered = false; + + switch lower(name) + case 'fs' + if isa(obj.parent,'mixture') && obj.parent.fs~=val + obj.parent.fs = val; + end + end + + end + + function cpObj = copyElement(obj) + %COPYELEMENT Overload copy method with additional functionality + + % Make a shallow copy of all properties + cpObj = copyElement@iosr.dsp.audio(obj); + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/audio.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/audio.m new file mode 100644 index 0000000000000000000000000000000000000000..e6b5888395104c86b929f8027c642f5530a2c8de --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/audio.m @@ -0,0 +1,239 @@ +classdef (Abstract) audio < matlab.mixin.Copyable +%AUDIO Abstract superclass providing audio-related properties and methods. +% +% The IOSR.DSP.AUDIO superclass is an abstract class that defines +% audio-related properties and methods. As an abstract class, it cannot +% be instantiated. +% +% IOSR.DSP.AUDIO is a subclass of MATLAB.MIXIN.COPYABLE, which is a +% subclass of the HANDLE class. Hence subclasses of AUDIO are handle +% classes. +% +% IOSR.DSP.AUDIO properties: +% filename - Name of the corresponding audio file +% fs - Sampling frequency (Hz) +% signal - The sampled data (read-only) +% +% IOSR.DSP.AUDIO methods: +% sound - Replay the audio signal +% Static methods: +% up_down_mix - Remix a source to a designated channel count +% normalize - Normalize an audio signal +% spat - Spatialise a sound using a SOFA file +% +% See also IOSR.BSS.MIXTURE, IOSR.BSS.SOURCE, HANDLE, +% MATLAB.MIXIN.COPYABLE. + +% Copyright 2016 University of Surrey. + + properties (AbortSet) + filename % Name of the audio file + fs = 16000 % Sampling frequency (Hz) + end + + properties (Abstract, Dependent, SetAccess = protected) + signal % The sampled data (read-only) + end + + properties (Access = protected) + rendered = false % Flag indicates whether files match object + end + + methods % public methods + + function obj = audio(filename,fs) + %AUDIO Create the audio object + + if nargin > 0 + obj.filename = filename; + end + if nargin > 1 + obj.fs = fs; + end + + end + + function sound(obj) + %SOUND Replay the audio signal + % + % IOSR.DSP.AUDIO.SOUND() replays the audio signal. + + obj.replay(obj.signal) + + end + + % validate properties + + % validate filename + function set.filename(obj,val) + assert(ischar(val) || isempty(val), 'iosr:audio:invalidFile', 'FILENAME must be a char array or an empty array') + obj.filename = val; + obj.property_changed('filename',val); + end + + % validate fs + function set.fs(obj,val) + assert(isscalar(val), 'iosr:audio:invalidFs', 'FS must be a scalar') + assert(val > 0, 'iosr:audio:invalidFs', 'FS must be greater than 0') + obj.fs = val; + obj.property_changed('fs',val); + end + + end + + methods (Access = protected) + + function property_changed(obj,name,val) %#ok<INUSD> + %PROPERTY_CHANGED handle property changes + + obj.rendered = false; + end + + function replay(obj,x) + %REPLAY Replay any audio signal + + sound(obj.normalize(x),obj.fs) % replay + + end + + function set_properties(obj,vgin,propNames) + %SET_PROPERTIES Parse varargin input to set object properties + % + % IOSR.DSP.AUDIO.SET_PROPERTIES(VGIN,PROPNAMES) searches through + % the cell array VGIN (a cell array of parameter/value pairs) for + % properties specified in the cell array PROPNAMES. Any matching + % properties are written to OBJ. + + % count arguments + nArgs = length(vgin); + if round(nArgs/2)~=nArgs/2 + error('iosr:audio:nameValuePair',[class(obj) ' needs propertyName/propertyValue pairs']) + end + % overwrite defults + for pair = reshape(vgin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},propNames); % find match parameter names + if any(IX) + % do the overwrite + obj.(propNames{IX}) = pair{2}; + else + error('iosr:audio:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + + end + + function cpObj = copyElement(obj) + %COPYELEMENT Overload copy method with additional functionality + + % Make a shallow copy of all properties + cpObj = copyElement@matlab.mixin.Copyable(obj); + + end + + end + + methods (Static) + + function [y,gain] = normalize(x) + %NORMALIZE Normalize an audio signal + % + % Y = IOSR.DSP.AUDIO.NORMALIZE(X) normalises X such that + % ABS(Y(:))<1. + % + % [Y,GAIN] = IOSR.DSP.AUDIO.NORMALIZE(X) returns the scalar gain + % GAIN applied to X in order to normalize it. + + gain = (1-((2*16)/(2^16)))/max(abs(x(:))); + y = x.*gain; + + end + + function y = spat(SOFAfile,x,azimuth,elevation,fs) + %SPAT Spatialise a sound using a SOFA file + % + % IOSR.DSP.AUDIO.SPAT(SOFAFILE,X,AZIMUTH,ELEVATION) spatialises + % the signal X using spatialisation data contained in the SOFA + % file SOFAFILE at the corresponding AZIMUTH and ELEVATION. The + % sampling frequency is that of the SOFA data. X should be a + % column vector; if it is not, it will be down-mixed to a column + % vector. + % + % IOSR.DSP.AUDIO.SPAT(...,FS) uses the sampling frequency FS for + % the spatialisation. If the SOFA data are not at the sampling + % rate FS, the data are resampled. + + assert(size(x,1)>1, 'iosr:audio:invalidX', 'X should be a column vector. Matrices will be downmixed to a column vector'); + + if size(x,2)>1 % mix to mono + x = audio.up_down_mix(x,1); + end + SOFAobj = SOFAload(SOFAfile); % load SOFA object + if ~exist('fs','var')==1 % set default FS + fs = SOFAobj.Data.SamplingRate; + end + + % convert navigational coordinates to spherical coordinates + if azimuth<0 + [azimuth,elevation] = nav2sph(azimuth,elevation); + end + + % find index of corresponding IR is SOFA obj + dist = (SOFAobj.SourcePosition(:,1)-azimuth).^2 + ... + (SOFAobj.SourcePosition(:,2)-elevation).^2; + [~,idx] = min(dist); + + % return IR + IR = squeeze(SOFAobj.Data.IR(idx,:,:))'; + + % resample? + if SOFAobj.Data.SamplingRate~=fs + disp(['Resampling audio to ' num2str(fs) ' Hz.']) + IR = resample(IR,fs,SOFAobj.Data.SamplingRate); + end + + % convolve + y = zeros(length(x)+size(IR,1)-1,size(IR,2)); + for c = 1:size(IR,2) + y(:,c) = iosr.dsp.convFft(x,IR(:,c)); + end + + % crop + y = y(1:length(x),:); + + end + + function y = up_down_mix(x,N) + %UP_DOWN_MIX Remix a source to a designated channel count + % + % Y = IOSR.DSP.AUDIO.UP_DOWN_MIX(X,N) mixes the signal X to have + % the specified channel count N. Data for each channel in X + % should be stored down its columns. For input channel count M, + % the up-/down-mix coefficients are calculated as + % ONES(M,N)./(M*N). + + M = size(x,2); + y = x*(ones(M,N)./(M*N)); + + end + + end + + methods (Static, Access = protected) + + function ensure_path(filename) + %ENSURE_PATH Ensure path exists for specified filename + + % get path + filepath = fileparts(filename); + if ~isempty(filepath) + % ensure path exits + if exist(filepath,'dir')~=7 + mkdir(filepath) + end + end + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/autocorr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/autocorr.m new file mode 100644 index 0000000000000000000000000000000000000000..32540d1df5908c46320fd621686d439f156242e3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/autocorr.m @@ -0,0 +1,35 @@ +function a = autocorr(x,Q,dim) +%AUTOCORR Perform autocorrelation via FFT +% +% IOSR.DSP.AUTOCORR(X) performs autocorrelation via FFT on vector X. For +% matrices, the autocorrelation is performed on each column. For N-D +% arrays, the autocorrelation is performed on the first non-singleton +% dimension. +% +% IOSR.DSP.AUTOCORR(X,Q) allows the sharpness of the autocorrelation to +% be controlled. Q=2 will give a true autocorrelation; smaller values +% will lead to sharper peaks. +% +% IOSR.DSP.AUTOCORR(X,[],DIM) or autocorr(X,Q,DIM) performs the +% autocorrelation along the dimension DIM. +% +% See also XCORR. + +% Copyright 2016 University of Surrey. + + if nargin < 2 || isempty(Q) + Q = 2; + end + + if nargin < 3 + nsdim = find(size(x)>1,1,'first'); + if isempty(nsdim) + dim = 1; + else + dim = nsdim; + end + end + + a = ifft(abs(fft(x,[],dim)).^Q,[],dim); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/convFft.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/convFft.m new file mode 100644 index 0000000000000000000000000000000000000000..6c0f2239a33737991f771500490b32ad8570c867 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/convFft.m @@ -0,0 +1,83 @@ +function c = convFft(a,b,shape) +%CONVFFT Convolve two vectors using FFT multiplication +% +% Convolution using traditional overlapping methods can be slow for very +% long signals. A more efficient method is to multiply the FFTs of the +% signals and take the inverse FFT of the result. However, this comes at +% a cost: FFT-based convolution is subject to floating-point round-off +% errors, and requires more memory [1]. +% +% C = IOSR.DSP.CONVFFT(A,B) convolves vectors A and B. The resulting +% vector is length: length(A)+length(B)-1. +% +% C = IOSR.DSP.CONVFFT(A,B,SHAPE) returns a subsection of the convolution +% with size specified by SHAPE: +% 'full' - (default) returns the full convolution, +% 'same' - returns the central part of the convolution that is the +% same size as a. +% 'valid' - returns only those parts of the convolution that are +% computed without the zero-padded edges. length(c) is +% L-2*(min(P,Q)-1) where P = numel(a), Q = numel(b), +% L = P+Q-1. +% +% Based on code written by Steve Eddins, 2009. +% +% References +% +% [1] http://blogs.mathworks.com/steve/2009/11/03/ +% the-conv-function-and-implementation-tradeoffs/ +% +% See also CONV. + +% Copyright 2016 University of Surrey. + + assert(isvector(a) & isvector(b), 'iosr:convFft:invalidInput', 'a and b must be vectors') + + if nargin<3 + shape = 'full'; + end + assert(ischar(shape), 'iosr:convFft:invalidShape', 'Unknown shape parameter') + + P = numel(a); + Q = numel(b); + L = P + Q - 1; + K = 2^nextpow2(L); + + % do the convolution + afft = fft(a, K); + bfft = fft(b, K); + c = ifft(afft(:).*bfft(:)); + + % specify index range for shape + switch lower(shape) + case 'full' + range = [1, L]; + case 'same' + range = [floor(length(b)/2)+1, L-ceil(length(b)/2)+1]; + case 'valid' + range = [min(P,Q), L-min(P,Q)+1]; + otherwise + error('iosr:convFft:unknownShape',['shape ''' shape ''' is invalid. The options are ''full'' (default), ''same'', or ''valid''.']) + end + + % crop to shape + c = c(range(1):range(2)); + + % restore orientation + if shape(1) == 'f' + if length(a) > length(b) + if size(a,1) == 1 %row vector + c = c.'; + end + else + if size(b,1) == 1 %row vector + c = c.'; + end + end + else + if size(a,1) == 1 %row vector + c = c.'; + end + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/istft.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/istft.m new file mode 100644 index 0000000000000000000000000000000000000000..c033ee0a73b6683521a94cf851ec2e58352374fe --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/istft.m @@ -0,0 +1,88 @@ +function [x,t] = istft(s,nfft,hop,fs) +%ISTFT Calculate the Inverse Short-Time Fourier Transform +% +% X = IOSR.DSP.ISTFT(S) calculates the inverse short-time Fourier +% transform (ISTFT), from the 1024-point one-sided FFTs in each column of +% S, using the overlap-add method. It is assumed that FFTs are calculated +% in steps of HOP=512. X is a column vector of length (HOP*K)+(NFFT-HOP) +% where K is SIZE(X,2). +% +% X = IOSR.DSP.ISTFT(S,NFFT) uses FFT-length NFFT and HOP=FIX(NFFT/2). +% +% X = IOSR.DSP.ISTFT(S,NFFT,HOP) uses the hop size HOP. +% +% [X,T] = IOSR.DSP.ISTFT(S,NFFT,HOP,FS) returns the corresponding time T +% (seconds) for each element of X based on sampling frequency FS. +% +% Example +% +% % create a spectrogram using a Hann window +% % and convert back to the time domain +% load handel.mat +% nfft = 1024; +% hop = 128; +% Y = iosr.dsp.stft(y,hann(nfft),hop); +% z = iosr.dsp.istft(Y,nfft,hop); +% +% See also IOSR.DSP.STFT. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(ismatrix(s), 'iosr:istft:invalidS', 'S must be a matrix') + + % check nfft + if nargin<2 + nfft = 1024; + else + assert(isscalar(nfft) && round(nfft)==nfft && nfft>0, 'iosr:istft:invalidNfft', 'NFFT must be a positive scalar integer') + end + + % determine hop size + if nargin<3 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:istft:invalidHop', 'hop must be an integer') + assert(hop<=nfft && hop>0, 'iosr:istft:invalidHop', 'hop must be less than or equal to nfft, and greater than 0') + end + + % determine fs + if nargin<4 + fs = 1; + else + assert(isscalar(fs), 'iosr:istft:invalidFs', 'FS must be an scalar') + end + + %% calculate outputs + + % calculate number of frames and samples + K = size(s,2); + M = (hop*K)+(nfft-hop); + + % calculate highest bin and correction for one-sided FFT + if mod(nfft,2)==0 + Nout = (nfft/2)+1; + ec = 1; + else + Nout = (nfft+1)/2; + ec = 0; + end + + % check FFT size + assert(size(s,1)==Nout, 'iosr:istft:invalidS', sprintf('SIZE(S,1) is not correct for an FFT-length of %d',nfft)) + + % calculate ISTFTs + x = zeros(M,1); + for k = 1:K + samples = ((k-1)*hop)+1:((k-1)*hop)+nfft; + Xtemp = [s(:,k); conj(s(end-ec:-1:2,k))]; + x(samples) = x(samples)+ifft(Xtemp); + end + + % calculate time + if nargout>1 + t = (0:M-1)./fs; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/lapwin.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/lapwin.m new file mode 100644 index 0000000000000000000000000000000000000000..c151d7fd60900109d58dc24d452b5e98d560bcee --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/lapwin.m @@ -0,0 +1,28 @@ +function w = lapwin(L,b) +%LAPWIN Laplace window. +% +% IOSR.DSP.LAPWIN(N) returns an N-point Laplace window. The window w(x) is +% calculated for -10<=x<=10. +% +% IOSR.DSP.LAPWIN(N,B) returns an N-point Laplace window using scale parameter B. +% If omitted, B is 2. +% +% See also GAUSSWIN, CHEBWIN, KAISER, TUKEYWIN, WINDOW. + +% Copyright 2016 University of Surrey. + + assert(isscalar(L) && round(L)==L, 'iosr:lapwin:invalidL', 'L must be a scalar and whole number.') + + if nargin<2 + b = 2; + else + assert(isscalar(b), 'iosr:lapwin:invalidB', 'b must be a scalar.') + end + + w = zeros(L,1); + N = L-1; + x = 10.*((0:N)'-N/2)./(N/2); + w(x<0) = exp(-(-x(x<0)./b)); + w(x>=0) = exp(-(x(x>=0)./b)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/localpeaks.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/localpeaks.m new file mode 100644 index 0000000000000000000000000000000000000000..bd261c04402b864b6bfb4d7d346845a957aff4c8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/localpeaks.m @@ -0,0 +1,42 @@ +function peaks = localpeaks(x,mode) +%LOCALPEAKS Find local peaks and troughs in a vector +% +% This function returns the indices of local peaks and/or troughs in a +% vector. +% +% PEAKS = IOSR.DSP.LOCALPEAKS(X) locates the local peaks in vector X. +% +% PEAKS = IOSR.DSP.LOCALPEAKS(X,MODE) locates local features specified by +% mode, which can be set to 'peaks' (default), 'troughs' in order to +% identify local troughs, or 'both' in order to identify both local peaks +% and troughs. + +% Copyright 2016 University of Surrey. + + assert(isvector(x), 'iosr:localpeaks:invalidX', 'Input must be a vector') + + if nargin < 2 + mode = 'peaks'; + end + + switch lower(mode) + case 'peaks' + % do nothing + peaks = find_peaks(x); + case 'troughs' + peaks = find_peaks(-x); + case 'both' + peaks = find_peaks(x) | find_peaks(-x); + otherwise + error('iosr:localpeaks:unknownMode','Unknown localpeak mode. Please specify ''peaks'', ''troughs'' or ''both'''); + end + +end + +function peaks = find_peaks(x) +%FIND_PEAKS find local peaks in a vector + + peaks = false(size(x)); + peaks(2:end-1) = sign(x(2:end-1)-x(1:end-2)) + sign(x(2:end-1)-x(3:end)) > 1; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/ltas.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/ltas.m new file mode 100644 index 0000000000000000000000000000000000000000..838cb2627d9564da23808b9239a099a2c14c21ef --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/ltas.m @@ -0,0 +1,219 @@ +function [s,f] = ltas(x,fs,varargin) +%LTAS calculate the long-term average spectrum of a signal +% +% S = IOSR.DSP.LTAS(X,FS) calculates the long-term average spectrum +% (LTAS) of signal X, sampled at FS Hz. The spectrum is calculated from +% the average power spectral density (PSD) obtained from a series of +% overlapping FFTs; the FFT length is 4096, and the hop size is 2048. The +% segments of X are Hann-windowed. The average PSD is then +% Gaussian-smoothed to 1/3-octave resolution. +% +% X can be a vector, matrix, or multidimensional array; LTAS will operate +% along the first non-signleton dimension, and return the LTAS for each +% corresponding row/column/etc. +% +% S = IOSR.DSP.LTAS(X,FS,'PARAMETER','VALUE') allows numerous parameters +% to be specified. These parameters are:- +% 'dim' : {find(size(X)>1,1,'first')} | scalar +% Specifies the dimension of operation (defaults to the first +% non-singleton dimension). +% 'graph' : {false} | true +% Choose whether to plot a graph of the LTAS. +% 'hop' : {NFFT/2} | scalar +% Specifies the step size through X used to calculate each +% segment. NFFT is determined by the 'win' parameter. +% 'noct' : {3} | scalar +% Apply 1/noct-octave smoothing to the frequency spectrum. +% Setting 'noct' to 0 results in no smoothing. +% 'scaling' : {'none'} | 'max0' +% Specifies any scaling to apply to S. By default, no scaling is +% applied. If scaling is set to 'max0', S will be scaled to have +% a maximum value of 0dB. +% 'units' : {dB} | 'none' +% Specifies the output units. By default the PSD is calculated in +% dB. Otherwise the PSD is returned directly. +% 'win' : {4096} | scalar | vector +% Specifies the window or FFT length NFFT used to calculate the +% spectrum. If 'win' is a scalar, it specifies the FFT length, +% and a Hann window is applied to each segment. If 'win' is a +% vector, NFFT is the length of the vector, and the vector is +% multiplied with each segment. +% +% [S,F] = IOSR.DSP.LTAS(...) returns the frequencies F for each +% corresponding bin of S. +% +% Example +% +% % Plot the 1/6th-octave-smoothed LTAS of the Handel example +% load handel.mat +% figure +% iosr.dsp.ltas(y,Fs,'noct',6,'graph',true); +% +% See also IOSR.DSP.STFT, IOSR.DSP.SMOOTHSPECTRUM. + +% Copyright 2016 University of Surrey. + + %% parse input + + if nargin < 2 + error('iosr:ltas:nargin''Not enough input arguments') + end + + options = struct(... + 'win',4096,... + 'hop',[],... + 'noct',3,... + 'dim',[],... + 'units','db',... + 'scaling','none',... + 'graph',false); + + % read parameter/value inputs + if nargin>2 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:ltas:nameValuePair','LTAS needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:ltas:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + %% check and assign input + + % required inputs + assert(isnumeric(x), 'iosr:ltas:invalidX', 'X must be numeric.'); + assert(isscalar(fs), 'iosr:ltas:invalidFs', 'FS must be a scalar.'); + assert(fs>0, 'iosr:ltas:invalidFs', 'FS must be greater than 0.'); + assert(isint(fs), 'iosr:ltas:invalidFs', 'FS must be an integer.'); + + % determine fft parameters + if numel(options.win)>1 && isvector(options.win) + NFFT = length(options.win); + win = options.win; + elseif isscalar(options.win) + NFFT = options.win; + win = NFFT; + else + error('iosr:ltas:invalidWin','''WIN'' must be a vector or a scalar'); + end + assert(isint(NFFT) && NFFT>0, 'iosr:ltas:invalidNfft', '''WIN'' must be a positive integer'); + + % determine hop + hop = options.hop; + if isempty(hop) + hop = fix(NFFT/2); + end + + % smoothing + Noct = options.noct; + + % dimension to operate along + dim = options.dim; + dims = size(x); + if isempty(dim) + dim = find(dims>1,1,'first'); + else + assert(isnumeric(dim),'iosr:ltas:invalidDim', 'DIM must be an integer'); + assert(isint(dim), 'iosr:ltas:invalidDim', 'DIM must be an integer or empty'); + assert(dim>0, 'iosr:ltas:invalidDim', 'DIM must be greater than 0') + end + + %% permute and rehape x to operate down columns + + % number of useful coefficients + if mod(NFFT,2)==0 + Nout = (NFFT/2)+1; + else + Nout = (NFFT+1)/2; + end + + % reorder and permute + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x = rearrange(x,order,[dims_shift(1) prod(dims_shift(2:end))]); + dims_out_shift = dims_shift; + dims_out_shift(1) = Nout; + + %% calculate spectra + + % choose units function + switch lower(options.units) + case 'db' + units = @(x) 10*log10(x); + max0scale = @(s) s-max(s(:)); + labelY = 'Power spectral density [dBFS]'; + yscale = 'linear'; + case 'none' + units = @(x) x; + max0scale = @(s) s./max(s(:)); + labelY = 'Power spectral density'; + yscale = 'log'; + otherwise + error('iosr:ltas:unknownUnits','Unknown units option ''%s''',options.units); + end + + % do calculations + s = zeros(dims_out_shift); + for c = 1:size(x,2) + [S,f] = iosr.dsp.stft(x(:,c),win,hop,fs); % short-time ft + s(:,c) = mean(abs(S/NFFT).^2,2); % mean PSD + s(:,c) = units(s(:,c)); % put into dB + s(:,c) = iosr.dsp.smoothSpectrum(s(:,c),f,Noct); % smooth + end + + % invert permutation + s = irearrange(s,order,dims_out_shift); + + % scale output + switch lower(options.scaling) + case 'max0' + s = max0scale(s); + case 'none' + % do nothing + otherwise + error('iosr:matchEQ:unknownScaling','Unknown scaling option ''%s''',options.scaling); + end + + %% plot + + assert(islogical(options.graph) && numel(options.graph)==1, 'iosr:ltas:invalidGraph', '''graph'' option must be logical.') + if options.graph + semilogx(f,rearrange(s,order,[dims_out_shift(1) prod(dims_out_shift(2:end))])); + xlabel('Frequency [Hz]'); + ylabel(labelY); + set(gca,'yscale',yscale); + grid on + if prod(dims_out_shift(2:end)) > 1 + legend(num2str((1:prod(dims_out_shift(2:end)))')); + end + end + +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end + +function y = isint(x) +%ISINT check if input is whole number + y = x==round(x); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/matchEQ.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/matchEQ.m new file mode 100644 index 0000000000000000000000000000000000000000..f2ff913dea2b4521f097e7b523350ccf1452bad1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/matchEQ.m @@ -0,0 +1,223 @@ +function [y,b] = matchEQ(x,fs,mag,f,varargin) +%MATCHEQ Match the LTAS of a signal to an arbitrary spectral magnitude +% +% Y = IOSR.DSP.MATCHEQ(X,FS,MAG,F) matches the long-term average spectrum +% of X, sampled at FS Hz, to the spectral magnitudes contained in vector +% MAG sampled at frequencies in vector F. X can be a vector, matrix, or +% multidimensional array; MATCHEQ will operate along the first +% non-signleton dimension. Y is the same size as X. +% +% Y = IOSR.DSP.MATCHEQ(X,FS,MAG,F,'PARAMETER','VALUE') allows numerous +% parameters to be specified. These parameters are:- +% 'dim' : {find(size(X)>1,1,'first')} | scalar +% Specifies the dimension of operation (defaults to the first +% non-singleton dimension). +% 'boostRatio' : {1} | scalar +% Determine the correction ratio for spectral regions that are +% amplified. By default, the 'ratio' parameter is used. See +% 'ratio' below. +% 'cutRatio' : {1} | scalar +% Determine the correction ratio for spectral regions that are +% attenuated. By default, the 'ratio' parameter is used. See +% 'ratio' below. +% 'hop' : {NFFT/2} | scalar +% Specifies the step size through X used to calculate each +% segment for the LTAS. NFFT is determined by the 'win' +% parameter. +% 'ltasNorm' : {'none'} | 'peak' | 'sum' +% Apply normalisation to the LTAS. By default, no normalisation +% is applied, and the equalisation will attempt to match the +% targtet magnitude. By setting the normalisation to 'peak', MAG +% and the LTAS of X are normalised in order to have a peak gain +% of unity before calculating the correction filter. By setting +% the normalisation to 'sum', MAG and the LTAS of X are +% normalised in order to sum to unity before calculating the +% correction filter. +% 'noct' : {3} | scalar +% Apply 1/noct-octave smoothing to the LTAS. Setting 'noct' to 0 +% results in no smoothing. +% 'order' : {2048} | scalar +% Determine the order of the correction filter. +% 'ratio' : {1} | scalar +% Determine the correction ratio. A value of 0 means that no +% correction is applied; 1 means that the full correction is +% applied; a value greater than 1 will over-correct. +% 'win' : {4096} | scalar | vector +% Specifies the window or FFT length NFFT used to calculate the +% LTAS. If 'win' is a scalar, it specifies the FFT length, +% and a Hann window is applied to each segment. If 'win' is a +% vector, NFFT is the length of the vector, and the vector is +% multiplied with each segment. +% +% [Y,B] = IOSR.DSP.MATCHEQ(...) returns the filter coefficients to the +% array B. B is the same size as X, except that the DIMth dimension of B +% has length N+1, where N is the filter order and DIM is the dimension of +% operation. +% +% Example +% +% % flatten the spectrum of the Handel example +% load handel.mat +% f = linspace(0,1,1024); +% mag = ones(size(f)); +% z = iosr.dsp.matchEQ(y,Fs,mag,f,'ltasNorm','sum'); +% +% See also IOSR.DSP.LTAS. + +% Copyright 2016 University of Surrey. + + %% parse input + + if nargin < 4 + error('iosr:matchEQ:nargin','Not enough input arguments') + end + + options = struct(... + 'win',4096,... + 'hop',[],... + 'noct',3,... + 'dim',[],... + 'ratio',1,... + 'boostRatio',[],... + 'cutRatio',[],... + 'order',2048,... + 'ltasNorm','none'); + + % read parameter/value inputs + if nargin>4 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:matchEQ:nameValuePair','MATCHEQ needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:matchEQ:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + %% check and assign input + + % required inputs + assert(isnumeric(x), 'iosr:matchEQ:invalidX', 'X must be numeric.'); + assert(isscalar(fs), 'iosr:matchEQ:invalidFs', 'FS must be a scalar.'); + assert(fs>0, 'iosr:matchEQ:invalidFs', 'FS must be greater than 0.'); + assert(isint(fs), 'iosr:matchEQ:invalidFs', 'FS must be an integer.'); + assert(isnumeric(mag) && isvector(mag), 'iosr:matchEQ:invalidMag', 'MAG must be a numeric vector.') + assert(isnumeric(f) && isvector(f), 'iosr:matchEQ:invalidF', 'F must be a numeric vector.') + assert(isequal(size(mag),size(f)), 'iosr:matchEQ:invalidInputs', 'F and MAG must be the same size.') + assert(all(f>=0), 'iosr:matchEQ:invalidF', 'Frequencies in F must be greater than or equal to 0.') + assert(all(mag>=0), 'iosr:matchEQ:invalidMag', 'Magnitudes in MAG must be greater than or equal to 0.') + + % dimension to operate along + dim = options.dim; + dims = size(x); + if isempty(dim) + dim = find(dims>1,1,'first'); + else + assert(isnumeric(dim), 'iosr:matchEQ:invalidDim', 'DIM must be an integer'); + assert(isint(dim), 'iosr:matchEQ:invalidDim', 'DIM must be an integer or empty'); + assert(dim>0, 'iosr:matchEQ:invalidDim', 'DIM must be greater than 0') + end + + f = f(:); + mag = mag(:); + + %% Determine ratios + + assert(options.ratio>=0 && isscalar(options.ratio), 'iosr:matchEQ:invalidRatio', 'Ratio must be a positive scalar.') + + if isempty(options.boostRatio) + boostRatio = options.ratio; + else + boostRatio = options.boostRatio; + end + + if isempty(options.cutRatio) + cutRatio = options.ratio; + else + cutRatio = options.cutRatio; + end + + assert(boostRatio>=0 && isscalar(boostRatio), 'iosr:matchEQ:invalidBoostRatio', 'BoostRatio must be a positive scalar.') + assert(cutRatio>=0 && isscalar(cutRatio), 'iosr:matchEQ:invalidCutRatio', 'CutRatio must be a positive scalar.') + + %% Determine normalisation + + switch lower(options.ltasNorm) + case 'none' + fltas = @(x) x; + case 'sum' + fltas = @(x) x./sum(x); + case 'peak' + fltas = @(x) x./max(x); + otherwise + error('iosr:matchEQ:unknownNorm','Unknown normalisation mode ''%s''',options.ltasNorm) + end + + %% permute and rehape x to operate down columns + + % reorder and permute + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x = rearrange(x,order,[dims_shift(1) prod(dims_shift(2:end))]); + dims_out_shift = dims_shift; + b_out_dims = dims_shift; b_out_dims(1) = options.order+1; + + %% EQ + + assert(isscalar(options.order) && options.order>0 && isint(options.order),... + 'iosr:matchEQ:invalidOrder', ... + 'ORDER must be a positive scalar integer.') + + % do calculations + y = zeros(size(x)); + b = zeros(b_out_dims); + for c = 1:size(x,2) + [mX,fX] = iosr.dsp.ltas(x(:,c),fs,... + 'hop',options.hop,... + 'noct',options.noct,... + 'win',options.win,... + 'units','none'); + mX = fltas(mX); + if ~isequal(fX(:),f) + mag = interp1(f,mag,fX,'spline','extrap'); + end + mag = fltas(mag); + matcher = sqrt(mag./mX); + matcher(matcher>1) = matcher(matcher>1).*boostRatio; + matcher(matcher<1) = matcher(matcher<1).*cutRatio; + b(:,c) = fir2(options.order,2.*fX./fs,matcher); + y(:,c) = filter(b(:,c),1,x(:,c)); + end + + % invert permutation + y = irearrange(y,order,dims_out_shift); + b = irearrange(b,order,b_out_dims); + +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end + +function y = isint(x) +%ISINT check if input is whole number + y = x==round(x); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/rcoswin.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/rcoswin.m new file mode 100644 index 0000000000000000000000000000000000000000..bf6dbc77b9e217b69f4b96c711f670b798f56902 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/rcoswin.m @@ -0,0 +1,23 @@ +function w = rcoswin(N) +%RCOSWIN Raised cosine window. +% +% IOSR.DSP.RCOSWIN(N) returns an N-point raised cosine window. +% +% See also GAUSSWIN, CHEBWIN, KAISER, TUKEYWIN, WINDOW. + +% Copyright 2016 University of Surrey. + + assert(isscalar(N) && round(N)==N, 'iosr:rcoswin:invalidN', 'N must be a scalar and whole number.') + assert(N > 0, 'iosr:rcoswin:invalidN', 'N must be greater than 0.') + + switch N + case 1 + w = 1; + case 2 + w = [.5; .5]; + otherwise + r = linspace(-pi,pi,N)'; + w = (cos(r)+1)/2; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/rms.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/rms.m new file mode 100644 index 0000000000000000000000000000000000000000..3b75a4fb31430a9144276b956a55d6a1e3ecf004 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/rms.m @@ -0,0 +1,22 @@ +function rms = rms(x,dim) +%RMS Calculate the rms of a vector or matrix +% +% RMS = IOSR.DSP.RMS(X) calculates the Root Mean Square of X along the +% first non-singleton dimension of vector or matrix X. For vectors, +% IOSR.DSP.RMS(X) is the RMS value of the elements in x. For matrices, +% IOSR.DSP.RMS(X) is a row vector containing the RMS value of each +% column. For N-D arrays, IOSR.DSP.RMS(X) is the RMS value of the +% elements along the first non-singleton dimension of X. +% +% RMS = IOSR.DSP.RMS(X,DIM) calculates the RMS of X along the dimension +% DIM. + +% Copyright 2016 University of Surrey. + + if nargin == 1 + dim = find(size(x)~=1,1,'first'); + end + + rms = sqrt(mean(x.^2,dim)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/sincFilter.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/sincFilter.m new file mode 100644 index 0000000000000000000000000000000000000000..ee7b5bfc09aaff6e389dec884f781c0a18e23c2f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/sincFilter.m @@ -0,0 +1,102 @@ +function y = sincFilter(x,Wn,N,dim) +%SINCFILTER Apply a near-ideal low-pass or band-pass brickwall filter +% +% Y = IOSR.DSP.SINCFILTER(X,WN) applies a near-ideal low-pass or +% band-pass brickwall filter to the array X, operating along the first +% non-singleton dimension (e.g. down the columns of a matrix). The +% cutoff frequency/frequencies are specified in WN. If WN is a scalar, +% then WN specifies the low-pass cutoff frequency. If WN is a two-element +% vector, then WN specifies the band-pass interval. WN must be 0.0 < WN < +% 1.0, with 1.0 corresponding to half the sample rate. +% +% The filtering is performed by FFT-based convolution of X with the sinc +% kernel. +% +% Y = IOSR.DSP.SINCFILTER(X,WN,N) allows the filter length to be +% specified. The default value is N=1025. The filter length is doubled in +% the band-pass case. In either case, if N is even the final filter +% length will be N+1. +% +% Y = IOSR.DSP.SINCFILTER(X,WN,N,DIM) applies the specified filter along +% the dimension DIM. +% +% Y = IOSR.DSP.SINCFILTER(X,WN,[],DIM) applies the specified filter along +% the dimension dim using the default filter length. +% +% See also IOSR.DSP.CONVFFT. + +% Copyright 2016 University of Surrey. + + %% test input + + assert(nargin>=2, 'iosr:sincFilter:nargin', 'Not enough input arguments') + assert((numel(Wn)==1 || numel(Wn)==2) & isnumeric(Wn), 'iosr:sincFilter:invalidWn', 'Wn must be a scalar or two-element vector.') + assert(isnumeric(x), 'iosr:sincFilter:invalidX', 'x must be a numeric array.') + assert(all(Wn<=1) & all(Wn>=0), 'iosr:sincFilter:invalidWn', 'Wn must be 0.0 < Wn < 1.0, with 1.0 corresponding to half the sample rate.') + dims = size(x); + if nargin<4 + dim = []; + else + assert(isint(dim) & numel(dim)==1, 'iosr:sincFilter:invalidDim', 'dim must be an integer') + assert(dim<=length(dims), 'iosr:sincFilter:invalidDim', 'dim must be less than or equal to the number of dimensions in x') + end + if nargin<3 + N = []; + elseif ~isempty(N) + assert(isscalar(N) & isint(N), 'iosr:sincFilter:invalidN', 'N must be an integer scalar.') + end + + %% assign defaults + + if isempty(N) + N = 1025; + end + if isempty(dim) + dim = find(dims>1,1,'first'); + end + + %% reshape input to matrix with requested dim made as first dimension + + % reshape data so function works down columns + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + x = permute(x,order); + dims_shift = dims(order); + x = reshape(x,dims_shift(1),numel(x)/dims_shift(1)); + y = zeros(size(x)); + + %% create filter kernel + + if numel(Wn)==1 % low-pass + n = -floor(N/2):floor(N/2); % create time base + B = sinc_kernel(Wn,n); % make kernel + else % band-pass + n = -N:N; % create time base + B = sinc_kernel(Wn(2),n)-sinc_kernel(Wn(1),n); % make kernel + end + + %% apply filter + + for N = 1:size(y,2) + y(:,N) = iosr.dsp.convFft(x(:,N),B,'same'); + end + + %% reshape out to match input + + y = reshape(y,dims_shift); + y = ipermute(y,order); + +end + +function k = sinc_kernel(Wn,n) +% SINC_KERNEL Make sinc kernel + + k = sinc(Wn*n).*Wn; + +end + +function y = isint(x) +% ISINT Test whether x is integer value (not type) + + y = x==round(x); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/smoothSpectrum.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/smoothSpectrum.m new file mode 100644 index 0000000000000000000000000000000000000000..6717ffa9c3ca1f5124d21c7b26624f52ec002dc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/smoothSpectrum.m @@ -0,0 +1,92 @@ +function x_oct = smoothSpectrum(X,f,Noct) +%SMOOTHSPECTRUM Apply 1/N-octave smoothing to a frequency spectrum +% +% X_OCT = IOSR.DSP.SMOOTHSPECTRUM(X,F,NOCT) applies 1/NOCT-octave +% smoothing to the frequency spectrum contained in vector X sampled at +% frequencies in vector F. X can be a log-, magnitude-, or +% power-spectrum. Setting Noct to 0 results in no smoothing. +% +% Algorithm +% +% The function calculates the i-th smoothed spectral coefficient X_OCT(i) +% as the sum of the windowed spectrum. The window is a Gaussian whose +% centre frequency is F(i), and whose standard deviation is proportional +% to F(i)/NOCT. +% +% Example +% +% % Calculate the 1/3-octave-smoothed power spectral density of the +% % Handel example. +% +% % load signal +% load handel.mat +% +% % take fft +% Y = fft(y); +% +% % keep only meaningful frequencies +% NFFT = length(y); +% if mod(NFFT,2)==0 +% Nout = (NFFT/2)+1; +% else +% Nout = (NFFT+1)/2; +% end +% Y = Y(1:Nout); +% f = ((0:Nout-1)'./NFFT).*Fs; +% +% % put into dB +% Y = 20*log10(abs(Y)./NFFT); +% +% % smooth +% Noct = 3; +% Z = iosr.dsp.smoothSpectrum(Y,f,Noct); +% +% % plot +% figure +% semilogx(f,Y,f,Z) +% grid on +% +% See also IOSR.DSP.LTAS, FFT. + +% Copyright 2016 University of Surrey. + + %% Input checking + + assert(isvector(X), 'iosr:smoothSpectrum:invalidX', 'X must be a vector.'); + assert(isvector(f), 'iosr:smoothSpectrum:invalidF', 'F must be a vector.'); + assert(isscalar(Noct), 'iosr:smoothSpectrum:invalidNoct', 'NOCT must be a scalar.'); + assert(isreal(X), 'iosr:smoothSpectrum:invalidX', 'X must be real.'); + assert(all(f>=0), 'iosr:smoothSpectrum:invalidF', 'F must contain positive values.'); + assert(Noct>=0, 'iosr:smoothSpectrum:invalidNoct', 'NOCT must be greater than or equal to 0.'); + assert(isequal(size(X),size(f)), 'iosr:smoothSpectrum:invalidInput', 'X and F must be the same size.'); + + %% Smoothing + + % calculates a Gaussian function for each frequency, deriving a + % bandwidth for that frequency + + x_oct = X; % initial spectrum + if Noct > 0 % don't bother if no smoothing + for i = find(f>0,1,'first'):length(f) + g = gauss_f(f,f(i),Noct); + x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient + end + % remove undershoot when X is positive + if all(X>=0) + x_oct(x_oct<0) = 0; + end + end + +end + +function g = gauss_f(f_x,F,Noct) +% GAUSS_F calculate frequency-domain Gaussian with unity gain +% +% G = GAUSS_F(F_X,F,NOCT) calculates a frequency-domain Gaussian function +% for frequencies F_X, with centre frequency F and bandwidth F/NOCT. + + sigma = (F/Noct)/pi; % standard deviation + g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian + g = g./sum(g); % normalise magnitude + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/stft.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/stft.m new file mode 100644 index 0000000000000000000000000000000000000000..3cf2e508315cb62c77aa887798d579303db0de1a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/stft.m @@ -0,0 +1,119 @@ +function [s,f,t] = stft(x,nfft,hop,fs) +%STFT Calculate the short-time Fourier transform of a signal +% +% S = IOSR.DSP.STFT(X) calculates the short-time Fourier transform (STFT) +% of signal X using 1024-point segments in steps (hops) of 512 points. S +% is a series of one-sided FFTs of size [N,K] where N is the number of +% frequency bins and K is the number of time frames, such that N=513 and +% K=FIX((LENGTH(X)-512)/512). A hamming window is applied to each time +% segment. The window is normalised such that it fulfills the constant +% overlap-add (COLA) criterion. Fulfilling the criterion is useful when +% resynthesising the signal using the ISTFT, as the magnitude of the +% output of the ISTFT will be retained. +% +% S = IOSR.DSP.STFT(X,NFFT) calculates the STFT using NFFT-point +% segments. The hop size is HOP=FIX(NFFT/2); +% K=FIX((LENGTH(X)-(NFFT-HOP))/HOP), and N depends on whether NFFT is odd +% or even. If NFFT is even, N=(NFFT/2)+1; if NFFT is odd, N=(NFFT+1)/2. +% +% S = IOSR.DSP.STFT(X,WINDOW) calculates the STFT with +% NFFT=LENGTH(WINDOW) and applies the vector WINDOW to each segment. The +% window is normalised such that it fulfills the constant overlap-add +% (COLA) criterion. The normalised window is calculated as +% HOP.*WINDOW./SUM(WINDOW). +% +% S = IOSR.DSP.STFT(X,WINDOW,HOP) steps through X by HOP samples. +% +% [S,W] = IOSR.DSP.STFT(...) returns the normalised frequencies for each +% bin to W. +% +% [S,F] = IOSR.DSP.STFT(X,WINDOW,HOP,FS) returns the frequencies for each +% bin to F according to sampling frequency FS. +% +% [S,F,T] = IOSR.DSP.STFT(...) returns the corresponding time T (seconds) +% for each column of S. +% +% Example +% +% % plot a spectrogram +% load handel.mat +% [Y,f,t] = iosr.dsp.stft(x,1024,128,Fs); +% figure +% imagesc(t,f,20.*(log10(abs(Y)))); +% set(gca,'ydir','normal') +% ylabel('Frequency [Hz]') +% xlabel('Time [s]') +% +% See also IOSR.DSP.ISTFT. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(isvector(x) && numel(x)>1, 'iosr:stft:invalidX', 'X must be a vector') + + % check nfft + if nargin<2 + nfft = 1024; + end + + % determine window + if numel(nfft)>1 + win = nfft; + assert(isvector(win), 'iosr:stft:invalidNfft', 'WINDOW must be a vector') + nfft = length(win); + else + assert(round(nfft)==nfft && nfft>0, 'iosr:stft:invalidNfft', 'NFFT must be a positive integer') + win = hamming(nfft); + end + + % check x length + assert(length(x)>=nfft, 'iosr:stft:invalidInput', 'X must have at least NFFT samples') + + % determine hop + if nargin<3 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:stft:invalidHop', 'HOP must be an integer') + assert(hop<=nfft && hop>0, 'iosr:stft:invalidHop', 'HOP must be less than or equal to NFFT, and greater than 0') + end + + % normalise window + win = hop.*win./sum(win); + + % determine fs + if nargin<4 + fs = 1; + else + assert(isscalar(fs), 'iosr:stft:invaldFs', 'FS must be an scalar') + end + + %% calculate outputs + + % calculate highest bin for one-sided FFT + if mod(nfft,2)==0 + Nout = (nfft/2)+1; + else + Nout = (nfft+1)/2; + end + + % calculate number of frames + K = fix((length(x)-(nfft-hop))/hop); + + % calculate STFTs + s = zeros(Nout,K); + for k = 1:K + samples = ((k-1)*hop)+1:((k-1)*hop)+nfft; + temp = fft(win.*x(samples)); + s(:,k) = temp(1:Nout); + end + + % calculate frequency and time + if nargout>1 + f = fs.*((0:Nout-1)./nfft)'; + end + if nargout>2 + t = (0:K-1).*(hop/fs); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/vsmooth.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/vsmooth.m new file mode 100644 index 0000000000000000000000000000000000000000..085b207eeff5ef165c1f1f08cac9208f9fbbee79 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+dsp/vsmooth.m @@ -0,0 +1,95 @@ +function y = vsmooth(x,frame,mode) +%VSMOOTH Smooth a vector using mathematical functions +% +% Y = IOSR.DSP.VSMOOTH(X,FRAME) smooths the input vector X by calculating +% the running RMS over a series of frames. FRAME specifies the frame +% characteristics; it can be set to: +% +% a scalar - this will be used as the length of the frame, the window +% will be rectangular +% a vector - this specifies the shape of the analysis window, the +% frame length will be length(frame). +% +% Y = IOSR.DSP.VSMOOTH(X,FRAME,MODE) allows the user to specify a +% different mathematical smoothing function in MODE. The options are: +% +% 'rms' - calculates the running rms (default) +% 'mean' - calculates the running mean (moving average filter) +% 'median' - calculates the running median +% +% NOTE: vsmooth uses a vectorized implementation that may be slow when x +% and/or frame are very large. The number of elements that are used for +% calculation is length(X)*max(FRAME,length(FRAME)). The algorithm +% vectorizes the operation by creating a matrix of indexes and extracting +% its diagonals. E.g. for a vector of length 4 and frame_length of 2, the +% algorithm creates a temporary zero-padded matix x2 from which it +% creates a set of indexes: +% +% 1 1 +% 2 2 +% 3 3 +% 4 4 +% 5 5 +% 6 6 +% +% It then extracts the diagonals where -length(x2) + frame_length <= k <= +% 0, yielding: +% +% 1 2 +% 2 3 +% 3 4 +% 4 5 +% +% this is used to index x2; operations are then performed along the rows. + +% Copyright 2016 University of Surrey. + + %% Gather inputs + + assert(isvector(x), 'iosr:vsmooth:vectorInput', '''x'' must be a vector') + + if isscalar(frame) + frame_length = frame; + window = ones(frame_length,1); + elseif isvector(frame) + window = frame; + frame_length = length(frame); + else + error('iosr:vsmooth:frameInvalid','''frame'' must be a vector or a scalar') + end + + if nargin<3 + mode = 'rms'; + end + + %% Smooth + + % zero pad + x2 = [zeros(ceil((frame_length)/2)-1,1); x(:); zeros(floor(frame_length/2),1)]; + + samples = (1:length(x2))'; + samples = samples(:,ones(frame_length,1)); + + % get indexes + index = spdiags(samples,0:-1:-length(x2)+frame_length); + + window2 = window(:,ones(1,length(x))); + + % do calculations + switch lower(mode) + case 'rms' + y = sqrt(mean((window2.*x2(index)).^2)); + case 'median' + y = median((window2.*x2(index))); + case 'mean' + y = mean((window2.*x2(index))); + otherwise + error('iosr:vsmooth:unknownMode','Unknown ''mode'' specified') + end + + % transpose if necessary + if size(y,1)~=size(x,1) + y = y'; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/chMap.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/chMap.m new file mode 100644 index 0000000000000000000000000000000000000000..6c82eb98d471262219592c0e0ec3bd4200b0c406 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/chMap.m @@ -0,0 +1,41 @@ +function cmap = chMap(M) +%CHMAP Create a monochrome-compatible colour map +% +% CMAP = IOSR.FIGURES.CHMAP returns a colour map CMAP (varying black - +% blue - green - yellow - white) that is monochrome-compatible, i.e. it +% produces a linear greyscale colour map. CMAP is size Mx3, where M is +% the length of the current figure's colormap. If no figure exists, +% MATLAB creates one. +% +% CMAP = IOSR.FIGURES.CHMAP(M) returns a colormap of length M. +% +% EXAMPLE +% +% figure; +% imagesc(sin(linspace(0,2*pi,1000))'*... +% sin(linspace(0,2*pi,1000))); +% colormap(iosr.figures.chMap(256)); +% axis image; +% colorbar +% +% See also IOSR.FIGURES.CMRMAP, GRAY. + +% Copyright 2016 University of Surrey. + + % default colormap size + if nargin < 1, M = size(get(gcf,'colormap'),1); end + + N = linspace(0,1,M)'; + + % Define red and blue components + R = (sin(((2.*N.^1.5)-1).*(pi/2))+1)./2; + B = ((N.^1.25)+((sin((N.^1.0).*(2*pi)))./1.75)); + % Calculate green to ensure monotonic luminance + G = (N - 0.2989.*R - 0.1140.*B)./0.5870; + + % Ensure map is in range [0,1] + cmap = [R G B]; + cmap = cmap-min(cmap(:)); + cmap = cmap./max(cmap(:)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/cmrMap.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/cmrMap.m new file mode 100644 index 0000000000000000000000000000000000000000..ba3f7faec7c049ef7525257b4f8466f85f466e0b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/cmrMap.m @@ -0,0 +1,60 @@ +function cmap = cmrMap(M) +%CMRMAP Create a monochrome-compatible colour map +% +% CMAP = IOSR.FIGURES.CMRMAP returns a colour map CMAP (varying black - +% purple - red - yellow - white) that is monochrome- compatible, i.e. it +% produces a monotonic greyscale colour map. CMAP is size M-by-3, where M +% is the length of the current figure's colormap. If no figure exists, +% MATLAB creates one. +% +% CMAP = IOSR.FIGURES.CMRMAP(M) returns a colormap of length M. +% +% The map is a slight modification to that suggested in [1]. +% +% EXAMPLE +% +% figure; +% imagesc(peaks(1000)); +% colormap(iosr.figures.cmrMap(256)); +% axis image; +% colorbar +% +% REFERENCE +% +% [1] Rappaport, C. 2002: "A Color Map for Effective Black-and-White +% Rendering of Color Scale Images", IEEE Antenna's and Propagation +% Magazine, Vol.44, No.3, pp.94-96 (June). +% +% See also IOSR.FIGURES.CHMAP, GRAY. + +% Copyright 2016 University of Surrey. + + % default colormap size + if nargin < 1, M = size(get(gcf,'colormap'),1); end + + % reference colour map + % adapted from article to produce more linear luminance + CMRref=... + [0 0 0; + 0.1 0.1 0.35; + 0.3 0.15 0.65; + 0.6 0.2 0.50; + 1 0.25 0.15; + 0.9 0.55 0; + 0.9 0.75 0.1; + 0.9 0.9 0.5; + 1 1 1]; + + % Interpolate colormap to colormap size + cmap = zeros(M,3); + for c = [1,3] + cmap(:,c) = interp1((1:9)',CMRref(:,c),linspace(1,9,M)','spline'); + end + % calculate green to ensure linear luminance + cmap(:,2) = (linspace(0,1,M)' - 0.2989.*cmap(:,1) - 0.1140.*cmap(:,3))./0.5870; + + % Limit to range [0,1] + cmap = cmap-min(cmap(:)); + cmap = cmap./max(cmap(:)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/multiwaveplot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/multiwaveplot.m new file mode 100644 index 0000000000000000000000000000000000000000..5355ad3aa0451133a4785396c849a6749dcaa176 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/multiwaveplot.m @@ -0,0 +1,286 @@ +function varargout = multiwaveplot(varargin) +%MULTIWAVEPLOT Stacked line plots from a matrix or vectors +% +% Multiwaveplot draws a series of stacked lines (one on top of the other) +% contained in the rows of an input 2-D matrix. Each line has a +% designated row on the plot; the first row is plotted at the bottom of +% the plot. +% +% IOSR.FIGURES.MULTIWAVEPLOT(Z) draws a series of lines contained in the +% rows of the matrix Z. +% +% IOSR.FIGURES.MULTIWAVEPLOT(X,Y,Z) plot the lines against the data in X +% and Y, such that X specifies the common x-data, and Y determines the +% vertical position of each row. Hence, length(X)==size(Z,2) and +% length(Y)==size(Z,1). +% +% Z may also be a vector, of the same length as X and Y; the data +% contained in X and Y will be used to construct a matrix for plotting. +% +% IOSR.FIGURES.MULTIWAVEPLOT(...,'parameter','value') allows a number of +% options to be specified. The options are: +% +% ({} indicates the default value) +% +% 'gain' : {1} | scalar +% This parameter scales the height of each line. With gain=1 +% (default), the height of the tallest line will be limited so as not +% to encroach on the adjacent line; all other lines are scaled +% accordingly. With gain~=1 the height of each line will +% decrease/increase by a factor gain. +% 'horizonWidth' : {1} | scalar +% The plot can be made to narrower (or wider) at the top, to give the +% impression of a horizon. This may be useful, for example, when y +% data represent time. With horizonWidth=1 (default), the top and +% bottom of the plot have the same width. With horizonWidth<1, the +% plot is narrower at the top by a factor of horizonWidth. With +% horizonWidth>1, the plot is narrower at the bottom by a factor of +% 1/horizonWidth. Specifying horizonWidth>1 will cause the x-axis to +% be moved to the top of the plot. +% 'horizonOffset' : {0} | scalar +% This parameter specifies the vanishing point of the horizon. With +% horizonOffset=0 (default), the vanishing point is in the centre. +% With horizonOffset=-1, the vanishing point is on the left of the +% plot. With horizonOffset=1, the vanishing point is on the right of +% the plot. Intermediate values specify intermediate vanishing +% points. +% 'mode' : {'plot'} | 'fill' +% This parameter plots the data with the specified mode. The default +% mode depends on gain: for gain<=1, mode defaults to 'plot' and +% plots lines for each row of Z. For gain>1, mode defaults to 'fill' +% and instead plots white patch objects for each row of Z, covering +% the area under each line, such that lines with a lower row index +% mask those with a higher row index. +% 'reverseY' : {false} | true +% Determine the order in which data are plotted vertically. With +% reverseY=false (default), the first row is plotted at the bottom of +% the plot. With reverseY=true, the first row is plotted at the top +% of the plot and the axis direction is reversed, but the horizon +% effect is unchanged. In both cases, lower rows are plotted in front +% of higher rows. +% +% H = IOSR.FIGURES.MULTIWAVEPLOT(...) returns a vector of handles to +% patch (for mode = 'fill') or lineseries (for mode = 'plot') graphics +% objects, one handle per line. +% +% See also FILL, PATCH, PLOT, IMAGESC. + +% Copyright 2016 University of Surrey. + + %% Derive inputs + + firstPar = find(cellfun(@(x) ~isnumeric(x),varargin),1,'first'); + if isempty(firstPar) + firstPar = nargin+1; + end + overrides = {}; + + % get inputs + switch firstPar-1 + case 1 + Z = varargin{1}; + X = []; + Y = []; + case 2 + error('iosr:multiwaveplot:nargin','Wrong number of input arguments.') + otherwise + X = varargin{1}; + X = reshape(X,1,length(X)); + Y = varargin{2}; + Y = reshape(Y,1,length(Y)); + Z = varargin{3}; + end + + if firstPar < nargin + overrides = varargin(firstPar:end); + end + + % derive data + if isvector(Z) + assert(~isempty(X), 'iosr:multiwaveplot:invalidX', 'If Z is a vector, you must specify X and Y.') + assert(~isempty(Y), 'iosr:multiwaveplot:invalidY', 'If Z is a vector, you must specify X and Y.') + % if vector, make matrix + assert(length(X)==length(Z) && length(Y)==length(Z), 'iosr:multiwaveplot:invalidInputs', 'If Z is a vector, X and Y must be vectors of the same length.') + x = unique(X)'; + y = unique(Y)'; + wave = NaN(length(y),length(x)); + for n = 1:length(x) + for m = 1:length(y) + IX = X==x(n) & Y==y(m); + wave(m,n) = mean(Z(IX)); + end + end + [r,~] = size(wave); + else + % if matrix + if isempty(X) + X = 1:size(Z,2); + end + if isempty(Y) + Y = 1:size(Z,1); + end + assert(ismatrix(Z), 'iosr:multiwaveplot:invalidZ', 'Z must be a 2-D matrix') + wave = Z; + [r,c] = size(wave); + assert(c==length(X), 'iosr:multiwaveplot:invalidX', 'X must be the same length as Z has columns.') + assert(r==length(Y), 'iosr:multiwaveplot:invalidY', 'Y must be the same length as Z has rows.') + if isempty(X) + x = 1:r; + else + x = reshape(X,1,length(X)); + end + if isempty(Y) + y = 1:c; + else + y = Y; + end + end + + % get options + + options = struct(... + 'gain',1,... + 'mode',[],... + 'horizonWidth',1,... + 'horizonOffset',0,... + 'reverseY',false); + + % read parameter/value inputs + if ~isempty(overrides) % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(overrides); + if round(nArgs/2)~=nArgs/2 + error('iosr:multiwaveplot:nameValuePair','MULTIWAVEPLOT needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(overrides,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:multiwaveplot:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % set default plot mode + if isempty(options.mode) + if options.gain > 1 + options.mode = 'fill'; + else + options.mode = 'plot'; + end + end + + assert(all(diff(x)>=0), 'iosr:multiwaveplot:invalidX', 'X must be increasing') + assert(all(diff(y)>=0), 'iosr:multiwaveplot:invalidY', 'Y must be increasing') + + %% Plot + + % horizon + assert(isscalar(options.horizonWidth), 'iosr:multiwaveplot:invalidHorizonWidth', '''horizonWidth'' must be a scalar.') + assert(isscalar(options.horizonOffset), 'iosr:multiwaveplot:invalidHorizonOffset', '''horizonOffset'' must be a scalar.') + assert(options.horizonWidth>=0, 'iosr:multiwaveplot:invalidHorizonWidth', '''horizonWidth'' must be greater than or equal to 0.') + assert(options.horizonOffset>=-1 && options.horizonOffset<=1, 'iosr:multiwaveplot:invalidHorizonOffset', '''horizonOffset'' must be in the range [-1,1].') + if options.reverseY % correct horizon when axis reversed + options.horizonWidth = 1/options.horizonWidth; + end + % calculate widths + horizonWidths = linspace(1,options.horizonWidth,length(y)); + horizonWidths = horizonWidths./max(horizonWidths); + horizonX = linspace(-1,1,length(x))-options.horizonOffset; + + % data scaling + if min(wave(:))>=0 + adjust = 1; % for positive data (e.g. correlograms) + if options.reverseY + y0 = y(end); + else + y0 = y(1); + end + else + adjust = 0.5; % for wave data varying on zero + if options.reverseY + y0 = y(end)+((options.gain*adjust)*(y(end)-y(end-1))); + else + y0 = y(1)-((options.gain*adjust)*(y(2)-y(1))); + end + end + + wave_max = max(abs(wave(:))); % scale relative to max of wave + + for n = 1:r + if ~all(wave(n,:)==0) % just in case all values are zero + wave(n,:) = (adjust/wave_max).*wave(n,:); + end + end + + scale = zeros(r,1); % this parameter allows for non-linear y-values, scaling each channel accordingly + h = zeros(r,1); + + % plot + ax = newplot; + hold on; + + % plotting order + if options.reverseY + set(ax,'ydir','reverse') + order = 1:r; + shift = @(z,y) y-z; + else + order = r:-1:1; + shift = @(z,y) z+y; + end + + for n = order + % calculate scaling factor + try + scale(n) = y(n+1)-y(n); + catch + scale(n) = y(n)-y(n-1); + end + wave(n,:) = wave(n,:).*scale(n); + % scale data for horizon effect + xinterp = interp1(horizonX,x,horizonWidths(n).*horizonX); + yscale = reshape(shift(options.gain.*wave(n,:),y(n)),1,size(wave,2)); + % plot + switch options.mode + case 'plot' + h(n) = plot(xinterp,yscale,'k'); + case 'fill' + xhor = [x(1) xinterp(1) xinterp xinterp(end) x(end)]; + yhor = [y(n) y(n) yscale y(n) y(n)]; + xa=[xhor(1) xhor xhor(end) xhor(1)]; + ya=[y0 yhor y0 y0]; + IX = ~(isnan(xa) | isnan(ya)); + h(n) = fill(xa(IX),ya(IX),'w'); + otherwise + error('iosr:multiwaveplot:unknownMode','Unknown MODE specified: must be ''fill'' or ''plot''') + end + end + + % look at every row to search for max, taking y offset into account + if options.reverseY + ymin = [y(1)-((options.gain*adjust)*(y(2)-y(1))) y0]; + else + ymin = [y0 y(end)+((options.gain*adjust)*(y(end)-y(end-1)))]; + end + + % set plot parameters + hold off + axis([min(x) max(x) ymin]); % set axis limits + set(gca,'layer','top') % move axis to top layer + ytick = get(gca,'ytick'); + set(gca,'ytick',ytick(ytick<=max(y))); % remove ticks beyond y limits + box on + if options.horizonWidth>1 + set(gca,'XAxisLocation','top') + end + + % output + varargout(1:nargout) = {h}; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/subfigrid.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/subfigrid.m new file mode 100644 index 0000000000000000000000000000000000000000..5358cd3e6f4b1ce3ffae16c623f6a00b1727c2d6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+figures/subfigrid.m @@ -0,0 +1,150 @@ +function pos = subfigrid(nrows,ncols,offset,scale) +%SUBFIGRID Create axis positions for subfigures +% +% The spacing of axes using the subplot command can be quite large, and +% manipulating axis positions after plotting can be tricky. For +% publication quality graphics, it is better to specify the subplot +% position directly, rather than using subplot indices. For example: +% +% figure +% subplot('position',[0.1 0.1 0.2 0.2]) +% plot(rand(20,1)) +% +% This function creates appropriate position vectors, for use in the +% above scenario, based on the number of subplots required. Optional +% scaling and offset parameters allow the size of each subplot to be +% fine-tuned, and space for axis labels to be allotted. All calculations +% are performed in normalized units. +% +% POS = IOSR.FIGURES.SUBFIGRID(NROWS,NCOLS) creates an array of positions +% for positioning axes as subfigures. The array has dimensions [M,P,N]: M +% is the subplot row, N is the subplot column, and P is the position +% vector. By default, each axis will be scaled such that [width height] +% will be [1/NCOLS 1/NROWS]. +% +% POS = IOSR.FIGURES.SUBFIGRID(NROWS,NCOLS,OFFSET) allows a margin OFFSET +% to be specified. This should be a four-element vector specifying the +% margins thus: [left right top bottom]. By default offset=[0 0 0 0]. +% Axes will be scaled to fill the remaining space. +% +% POS = IOSR.FIGURES.SUBFIGRID(NROWS,NCOLS,OFFSET,SCALE) allows the axes +% to be scaled. This should be a two-element vector specifying a scale +% factor that will be applied to each axis; SCALE(1) scales the width, +% SCALE(2) scales the height. The axes will be scaled such that the +% offset margin will be retained. By default SCALE=[1 1]. +% +% If scaling is required, but an offset is not, OFFSET may be set to the +% empty matrix []. +% +% Examples +% +% Example 1 +% +% % Normal use of subfigrid +% scrsz = get(0,'ScreenSize'); +% nrows = 2; +% ncols = 3; +% pos = iosr.figures.subfigrid(nrows,ncols,... +% [0.05 0.01 0.01 0.05],[0.85 0.88]); +% +% figure('units','pixels','position',... +% [scrsz(3)/4,scrsz(4)/4,scrsz(3)/2,scrsz(4)/2]) +% for m = 1:nrows +% for n = 1:ncols +% subplot('position',pos(m,:,n)) +% plot(randn(20,1)) +% end +% end +% +% Example 2 +% +% % Use ind2sub when row/col indices are not available +% scrsz = get(0,'ScreenSize'); +% nrows = 2; +% ncols = 3; +% pos = iosr.figures.subfigrid(nrows,ncols,... +% [0.05 0.01 0.01 0.05],[0.85 0.88]); +% +% figure('units','pixels','position',... +% [scrsz(3)/4,scrsz(4)/4,scrsz(3)/2,scrsz(4)/2]) +% for p = 1:nrows*ncols +% [m,n] = ind2sub([nrows ncols],p); +% subplot('position',pos(m,:,n)) +% plot(randn(20,1)) +% end +% +% See also SUBPLOT. + +% Copyright 2016 University of Surrey. + + %% parse inputs + + if nargin<3 + offset = []; + end + if nargin<4 + scale = []; + end + + assert(isscalar(nrows) & round(nrows)==nrows, 'iosr:subfigrid:invalidInput', 'nrows must be a whole number scalar') + assert(isscalar(ncols) & round(ncols)==ncols, 'iosr:subfigrid:invalidInput', 'ncols must be a whole number scalar') + assert(nrows>=1 & ncols>=1, 'iosr:subfigrid:invalidInput', 'nrows and ncols must be greater than, or equal to, 1.') + + if isempty(offset) + offset = zeros(1,4); + elseif ~(isnumeric(offset) && numel(offset)==4) + error('iosr:subgigrid:offsetInvalid','offset should be a four-element numeric vector') + elseif any(offset<0) + error('iosr:subgigrid:offsetInvalid','offset should not contain any negative values') + else + offset = offset(:)'; + end + + if isempty(scale) + scale = [1 1]; + elseif ~(isnumeric(scale) && numel(scale)==2) + error('iosr:subgigrid:scaleInvalid','scale should be a two-element numeric vector') + elseif any(scale>1) || any(scale<0) + error('iosr:subgigrid:scaleInvalid','scale values should be in the range [0,1]') + else + scale = scale(:)'; + end + + %% calculate positions + + % ignore scale values for dimensions where there is one unit. + if ncols==1 && scale(1)<1 + scale(1) = 1; + warning('iosr:subgigrid:scaleUse','Since there is only one column, scale(1) has no effect (and is consequently set to 1).') + end + if nrows==1 && scale(2)<1 + scale(2) = 1; + warning('iosr:subgigrid:scaleUse','Since there is only one row, scale(2) has no effect (and is consequently set to 1).') + end + + % calculate array of left positions + sub_pos_l = linspace(offset(1),1-offset(2),ncols+1); + width = min(abs(diff(sub_pos_l)))*scale(1); + sub_pos_l = sub_pos_l(1:end-1); + % shift axes to maintain right margin: + sub_pos_l = sub_pos_l+linspace(0,((1-scale(1))*width),ncols); + + % calculate array of bottom positions + sub_pos_b = linspace(1-offset(3),offset(4),nrows+1); + height = min(abs(diff(sub_pos_b)))*scale(2); + sub_pos_b = sub_pos_b(2:end); + % shift axes to maintain top margin: + sub_pos_b = sub_pos_b+linspace(((1-scale(2))*height),0,nrows); + + % create array of positions + pos = zeros(nrows,4,ncols); + for m = 1:nrows + for n = 1:ncols + pos(m,1,n) = sub_pos_l(n); % left + pos(m,2,n) = sub_pos_b(m); % bottom + end + end + pos(:,3,:) = width; + pos(:,4,:) = height; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/cell2csv.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/cell2csv.m new file mode 100644 index 0000000000000000000000000000000000000000..0463ac4b6f55120da9d624d372c57ba80644a487 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/cell2csv.m @@ -0,0 +1,60 @@ +function cell2csv(C,filename) +%CELL2CSV Output a cell array to a CSV file +% +% IOSR.GENERAL.CELL2CSV(C,FILENAME) writes the cell array C to a CSV file +% specified by filename. + +% Copyright 2016 University of Surrey. + + %% make sure filename has a .csv extension + + [pathstr, name, ext] = fileparts(filename); + if ~strcmp(ext,'.csv') + filename = [pathstr filesep name '.csv']; + end + + %% write data + + [nrows,ncols]= size(C); + + % trap and remove cell arrays of strings + IX = cell2mat(cellfun(@iscell,C,'UniformOutput',false)); + C(IX) = cellfun(@char,C(IX),'UniformOutput',false); + + % create file + fid = fopen(filename, 'w'); + + % create format string + format = cell(1,ncols); + ind = cellfun(@ischar,C(2,:)); + format(ind) = {'%s,'}; + format(~ind) = {'%f,'}; + format = wrap(format); + + if any(cellfun(@ischar,C(1,:))~=cellfun(@ischar,C(2,:))) + % the cell array has a heading line + header = repmat({'%s,'},[1,ncols]); + header = wrap(header); + start = 2; + fprintf(fid, header, C{1,:}); + else + % the cell array does not have a heading line + start = 1; + end + + for row=start:nrows + fprintf(fid, format, C{row,:}); + end + + fclose(fid); + +end + +function y = wrap(x) +%WRAP Concatenate cells and add end EOL + + y = cell2mat(x); + i = strfind(y,','); + y = [y(1:i(end)-1) '\n']; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/checkMexCompiled.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/checkMexCompiled.m new file mode 100644 index 0000000000000000000000000000000000000000..2abf94735652006bcbbdc49383c55f38b877c85c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/checkMexCompiled.m @@ -0,0 +1,65 @@ +function checkMexCompiled(varargin) +%CHECKMEXCOMPILED Check if mex file is compiled for system +% +% IOSR.GENERAL.CHECKMEXCOMPILED(SOURCE_FILE) checks whether a mex source +% file SOURCE_FILE is compiled for the current operating system OR +% whether the source file has been modified since it was compiled. It is +% compiled if it does not pass these tests (to the same directory as the +% source file). SOURCE_FILE must be a string that is the name of a source +% file on the MATLAB search path. +% +% IOSR.GENERAL.CHECKMEXCOMPILED(OPTIONS,...,SOURCE_FILE) passes the +% script switches in OPTIONS to the mex compiler, one argument per +% switch. +% +% Example +% +% % check function compiled, with debugging info, and +% % with large-array-handling API +% iosr.general.checkMexCompiled('-g','-largeArrayDims','myfun.c') +% +% See also MEX. + +% Copyright 2016 University of Surrey. + + source_file = varargin{end}; + + % Check input filename + assert(ischar(source_file), 'iosr:checkMexCompiled:invalidFile', 'source_file must be a string') + + % Check extension is specified + assert(~isempty(strfind(source_file,'.')), 'iosr:checkMexCompiled:invalidFile', 'source_file: no file extension specified') + + % Locate source file + [pathstr,name,ext] = fileparts(which(source_file)); + + filename = [pathstr filesep name ext]; % Create filename + mexfilename = [pathstr filesep name '.' mexext]; % Deduce mex file name based on current platform + + if strcmp(pathstr,'') % source file not found + error('iosr:checkMexCompiled:fileNotFound',[source_file ': not found']) + elseif exist(mexfilename,'file')~=3 || get_mod_date(mexfilename)<get_mod_date(filename) + % if source file does not exist or it was modified after the mex file + disp(['Compiling "' name ext '".']) + d = cd; + cd(pathstr) + % compile, with options if appropriate + if length(varargin)>1 + options = varargin{1:end-1}; + mex(options,source_file) + else + mex(source_file) + end + disp('Done.') + cd(d) + end + +end + +function datenum = get_mod_date(file) +%GET_MOD_DATE get file modified date + + d = dir(file); + datenum = d.datenum; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/getContents.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/getContents.m new file mode 100644 index 0000000000000000000000000000000000000000..33f57d642d1e798e235ff88f07bb5919cd0cab6e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/getContents.m @@ -0,0 +1,183 @@ +function [cont,dirflag] = getContents(directory,varargin) +%GETCONTENTS Get the contents of a specified directory +% +% This function returns the contents of a specified directory. +% +% CONT = IOSR.GENERAL.GETCONTENTS(DIRECTORY) returns the files and +% folders in a directory and returns them to the cell array cont. It +% ignores hidden files and folders (those starting '.'). DIRECTORY must +% be a character array (string). +% +% CONT = IOSR.GENERAL.GETCONTENTS(DIRECTORY,'PARAMETER',VALUE) allows +% search options to be specified. The options include: +% 'rec' {false} | true +% Search recursively within the subfolders of the +% specified directory. +% 'path' {'relative'} | 'full' +% Specifies whether returned paths are full or relative +% to the specified directory. +% 'sort' {false} | true +% Specify whether the output is sorted alphabetically. +% 'filter' {'all'} | 'files' | 'folders' | '*.ext' | str +% This option allows a filter to be specified. 'files' +% returns names of all files in the directory. 'folders' +% returns names of all folders in the directory. '*.ext', +% where 'ext' is a user-specified file extension, returns +% all files with the extension '.ext'. str may be any +% string; only elements that contain str will be returned +% (files or folders). str is case-sensitive. +% +% [CONT,DIRFLAG] = IOSR.GENERAL.GETCONTENTS(...) returns a logical array +% DIRFLAG, the same size as CONT, indicating whether each element is a +% directory. +% +% Examples +% +% Ex. 1 +% +% % Return all m-files in the current directory +% +% cont = iosr.general.getContents(cd,'filter','*.m') +% +% Ex. 2 +% +% % Return all files in the current directory and its +% % sub-directories +% +% cont = iosr.general.getContents(cd,'rec',true) +% +% Ex. 3 +% +% % Return all files in current directory with names +% % containing 'foo' +% +% % may return files and folders: +% [cont,dirflag] = iosr.general.getContents(cd,'filter','foo') +% +% % use dirflag to limit: +% cont = cont(~dirflag); + +% Copyright 2016 University of Surrey. + + % parse input arguments and arrange call(s) to 'main', which + % does the actual searching of directories + + assert(ischar(directory), 'iosr:getContents:invalidDir', 'directory must be a character array') + + % Switch trap parses the varargin inputs + % default values + recflag = false; + pathflag = 'relative'; + sortflag = false; + str = 'all'; + % find values + for i = 1:2:length(varargin) + switch lower(varargin{i}) + case 'path' + pathflag=varargin{i+1}; + case 'rec' + recflag=varargin{i+1}; + case 'sort' + sortflag=varargin{i+1}; + case 'filter' + str=varargin{i+1}; + otherwise + error('iosr:getContents:unknownOption','Unknown option: %s\n',varargin{i}); + end + end + + % check input options + assert(ischar(pathflag), 'iosr:getContents:invalidPath', '''path'' option must be a string') + assert(strcmp(pathflag,'relative') | strcmp(pathflag,'full'),... + 'iosr:getContents:invalidPath', ... + '''path'' option must ''relative'' or ''full''') + assert(islogical(recflag) & numel(recflag)==1, 'iosr:getContents:invalidRec', '''rec'' option must be logical') + assert(islogical(sortflag) & numel(sortflag)==1, 'iosr:getContents:invalidSoftFlag', '''sort'' option must be a logical') + assert(ischar(str), 'iosr:getContents:invalidStr', 'str must be a character array') + + % first pass: contents of top-level folder + [cont,dirflag] = main(directory,str); + + % do the recursive bit, if recursion is requested + if recflag + dirs = main(directory,'folders'); + count = length(dirs); + n = 1; + while n <= count % recursion requested + [cont_temp,dirflag_temp] = main(dirs{n},str); % search them + cont = [cont; cont_temp]; %#ok<AGROW> append search results + dirflag = [dirflag; dirflag_temp]; %#ok<AGROW> append search results + sdirs = main(dirs{n},'folders'); + dirs = [dirs; sdirs]; %#ok<AGROW> + count = length(dirs); + n = n+1; + end + end + + % remove full path + if strcmp(pathflag,'relative') + if ~strcmp(directory(end),filesep) + directory = [directory filesep]; + end + for n = 1:length(cont) + cont{n} = strrep(cont{n}, directory, ''); + end + end + + % sort output (case insensitive) + if sortflag + [~,IX] = sort(lower(cont)); + cont = cont(IX); + dirflag = dirflag(IX); + end + +end + +function [cont,dirflag] = main(directory,str) +%MAIN get the contents + + list = struct2cell(dir(directory)); + dirbool = cell2mat(list(cellfun(@islogical,list(:,1)),:)); % return directory flags + list = list(1,:); % keep only file names + X = ~strncmp(list, '.', 1); % remove hidden files (those starting '.') + list = list(X); + list = list(:); % make column vector + dirbool = dirbool(X); + dirbool = dirbool(:); % make column vector + + for n = 1:length(list) + list{n} = fullfile(directory,list{n}); + end + + if nargin > 1 + % find filename extensions + exts = cell(size(list)); + for n = 1:length(list) + [~,~,exts{n}] = fileparts(list{n}); + end + % filter + if strncmp(str,'*.',2) % if extensions are requested + ext = str(2:end); + str = 'ext'; + end + switch lower(str) + case 'files' + Y = ~dirbool; + case 'folders' + Y = dirbool; + case 'ext' + Y = strcmp(exts,ext); + case 'all' + Y = true(size(dirbool)); + otherwise % use literal search string + Y = ~cellfun(@isempty,strfind(list,str)); + end + else + Y = true(size(list)); + end + + % return search results + cont = list(Y); + dirflag = dirbool(Y); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/updateContents.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/updateContents.m new file mode 100644 index 0000000000000000000000000000000000000000..af61ac820958235893ccbd500230529b46b237f7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/updateContents.m @@ -0,0 +1,154 @@ +function updateContents(folder) +%UPDATECONTENTS Create a Contents.m file including subdirectories +% +% IOSR.GENERAL.UPDATECONTENTS scans through the current directory, and +% its subdirectories, and builds a Contents file similar to Matlab's +% report-generated Contents.m files. Any existing Contents.m file will be +% overwritten. +% +% IOSR.GENERAL.UPDATECONTENTS(FOLDER) scans through the directory FOLDER. +% +% Typing +% +% help(FOLDER) +% +% or +% +% help path/to/folder +% +% will display Contents.m in the Command Window, and display links to the +% help for any functions that are in Matlab's search path. +% +% NB: Do not use Matlab's Contents Report generator to edit the +% Contents.m file. Execute this function to update it. + +% Copyright 2016 University of Surrey. + + % apply function in current directory + if nargin<1 + folder = cd; + end + + % check input is valid + assert(ischar(folder), 'iosr:updateContents:invalidPath', '''directory'' should be a charater array (string)') + assert(exist(folder,'dir')==7, 'iosr:updateContents:invalidPath', [folder ' does not exist']) + + % check last character in path is not filesep (e.g. '/') + if strcmp(folder(end),filesep) + folder = folder(1:end-1); + end + fIX = strfind(folder,filesep); fIX = fIX(end); + + % name of file to create + filename = 'Contents.m'; + + % Name of the folder + [~,name] = fileparts(folder); + + % delete if it already exists + if exist([folder filesep filename],'file')==2 + delete([folder filesep filename]) + end + + % get subfolders + dirs = iosr.general.getContents(folder,'filter','folders','rec',true,'path','full','sort',true); + dirs = [{folder}; dirs]; + + % get files + files = cell(0,1); + H1_lines = cell(0,1); + for d = 1:length(dirs) + temp = iosr.general.getContents(dirs{d},'filter','files','sort',true); + if ~isempty(temp) + temp = temp(cellfun(@(x) isempty(strfind(x,'~')),temp)); % remove temporary files + temp = temp(cellfun(@(x) isempty(strfind(x,'.mex')),temp)); % remove compiled mex files + temp = temp(cellfun(@(x) ~strcmp(x,filename),temp)); % remove Contents.m + H1_lines = [H1_lines; {''}; {''}]; %#ok<AGROW> % insert blank lines where no functions will be + % determine package prefix + pkgprefix = strrep(dirs{d},[filesep '+'],'.'); + pkgprefix = strrep(pkgprefix,[filesep '@'],'.'); + dots = strfind(pkgprefix,'.'); + if ~isempty(dots) + pkgprefix = [pkgprefix(dots(1)+1:end) '.']; + else + pkgprefix = ''; + end + for f = 1:length(temp) % read H1 lines + H1_lines = [H1_lines; {get_H1_line([dirs{d} filesep temp{f}])}]; %#ok<AGROW> % add H1 lines + % remove extension from and add package prefix to m-files + [~,fname,ext] = fileparts(temp{f}); + if strcmpi(ext,'.m') + temp{f} = [pkgprefix fname]; + end + end + files = [files; {''}; {upper(dirs{d}(fIX+1:end))}; temp;]; %#ok<AGROW> % add filenames + end + end + + % longest file name (so appropriate space can be added between files and H1 lines + longest_word = max(cellfun(@length,files(cellfun(@(x) ~isempty(x),H1_lines)))); + + % write to output + nrows = length(files); + fid = fopen(filename, 'w'); % open file for writing + fprintf(fid, '%s\n%% \n', ['% ' upper(name)]); + fprintf(fid, '%s\n', ['% Contents file for ' upper(folder(fIX+1:end)) ' and its subfolders.']); + for row=1:nrows + if isempty(H1_lines{row}) + fprintf(fid, '%s\n', ['% ' files{row,:}]); + else + rowfilename = files{row,:}; + [~,name,ext] = fileparts(rowfilename); + if strcmpi(ext,'.m') % remove extension from m files + rowfilename = name; + end + fprintf(fid, '%s\n',['% ' rowfilename repmat(' ',1,longest_word-length(rowfilename)) ' - ' H1_lines{row,:}]); + end + end + fprintf(fid, '%% \n%% %s on %s at %s.\n', 'This file was generated by updateContents.m',datestr(datetime('now'),'dd mmm yyyy'),datestr(datetime('now'),'HH:MM:SS')); + fclose(fid); + +end + +function H1_line = get_H1_line(filename) +%GET_H1_LINE get the H1 line for a file + + [~,name,ext] = fileparts(filename); + H1_line = ''; % default output + if strcmp(ext,'.m') + fid = fopen(filename); % open file + tline = fgetl(fid); % read first line + while ischar(tline) + k = strfind(tline,'%'); % find comment + if ~isempty(k) % if it is found + k = k(1); + ispercents = false(size(tline(k:end))); + ispercents(strfind(tline(k:end),'%'))=true; + start = k+find(~(isspace(tline(k:end)) | ispercents),1,'first')-1; + if ~isempty(start) + tline = tline(start:end); % remove leading space/percent + IX = strfind(lower(tline),lower(name)); + if ~isempty(IX) + if IX(1)==1 + tline = tline(length(name)+1:end); % remove function name + end + tline = strtrim(tline); % remove any leading/trailing space + end + H1_line = tline; + H1_line = strtrim(H1_line); + if ~isempty(H1_line) + if strcmp(H1_line(end),'.') % remove trailing period + H1_line = H1_line(1:end-1); + end + H1_line(1) = upper(H1_line(1)); % capitalize first letter + end + end + tline = -1; % set tline to numeric + else + tline = fgetl(fid); % read next line + end + end + fclose(fid); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/urn.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/urn.m new file mode 100644 index 0000000000000000000000000000000000000000..3feb65a0685938773064af08c1fcd5fc26122e1b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+general/urn.m @@ -0,0 +1,66 @@ +function r = urn(varargin) +%URN Generate random number sequence without duplicates +% +% IOSR.GENERAL.URN(N) returns an N-by-N matrix containing a random +% sequence of integers in the interval 1:N without duplicates. The +% integers are unique down each column. +% +% IOSR.GENERAL.URN(M,N) and IOSR.GENERAL.URN([M,N]) return an M-by-N +% matrix. +% +% IOSR.GENERAL.URN(M,N,P,...) and IOSR.GENERAL.URN([M,N,P,...]) return an +% M-by-N-by-P-by-... array. The integers are unique along the first +% non-singleton dimension. +% +% IOSR.GENERAL.URN(...,[],DIM) creates the random sequence along the +% dimension dim. +% +% This function uses a simple algorithm whereby a series or +% uniformly-distributed random numbers are generated and sorted. The +% returned array r is simply the array of indices specifying the sort +% order. +% +% The function was inspired by an object of the same name in Cycling 74's +% Max/MSP. + +% Copyright 2016 University of Surrey. + + % determines whether dimension specified + dimcheck = false; + + % find an empty matrix in input + empties = find(cellfun(@isempty,varargin)); + if ~isempty(empties) + % if there is an empty matrix (dim specified) + range = 1:empties-1; % input array-size-data range + if length(varargin)>empties % check extra dim input specified + dimcheck = true; % dim has been specified + dim = varargin{empties+1}; % get dim + else + warning('iosr:urn:nodim','Empty array but no dim specified. Using default.') + end + else + % input array-size-data range if no dim specified + range = 1:length(varargin); + end + + % input array-size-data at input + n = cell2mat(varargin(range)); + + % random numbers + c = rand(n); + + % If dim unspecified, find first non-singleton dimension + if ~dimcheck + nsdim = find(size(c)>1,1,'first'); + if isempty(nsdim) + dim = 1; + else + dim = nsdim; + end + end + + % sort the sequence, keeping sort indices as random integers + [~,r] = sort(c,dim); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/boxPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/boxPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..2a9de943648ffbebb7fed510aed72cf913640498 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/boxPlot.m @@ -0,0 +1,2410 @@ +classdef (CaseInsensitiveProperties = true) boxPlot < iosr.statistics.statsPlot +%BOXPLOT Draw a box plot +% +% Use this class to draw box plots. The class provides a number of +% options not included in Matlab's boxplot function. +% +% For each box, the central mark is the median, the box extends +% vertically between the 25th and 75th percentiles, the whiskers extend +% to the most extreme data that are not considered outliers, and the +% outliers are plotted individually. +% +% BOXPLOT can draw boxes for data in Y for an arbitrary number of +% dimensions. If Y is an N-by-P-by-G-by-I-by-J... array then G*I*J*... +% boxes are plotted hierarchically for each column P; i.e. J boxes are +% plotted for each index of I, and J*I boxes are plotted for each index +% of G. +% +% IOSR.STATISTICS.BOXPLOT properties: +% Plotting options: +% addPrctiles - Show additional percentiles using markers and +% labels. The property should be a vector of +% percentiles; each percentile will be plotted +% for each box. The property is empty by +% default. +% addPrctilesColor - Specify the marker color for the additional +% percentile markers. The property should be a +% cell array of strings indicating the color +% for each percentile; the colors will be +% repeated for each box. The default is black. +% addPrctilesLabels - Specify labels for the additional +% percentiles. The property should be a cell +% array of strings. By defualt no label +% is shown. +% addPrctilesMarkers - Specify markers for the additional +% percentiles. The property should be a cell +% array of strings indicating the shape of each +% percentile; the markers will be repeated for +% each box. The default is '*'. +% addPrctilesSize - Specify the marker size for the additional +% percentile markers. The property should be a +% numeric vector indicating the size for each +% percentile; the markers will be repeated for +% each box. The default is 6. +% addPrctilesTxtSize - Specify the font size of the additional +% percentile labels. The property should be a +% numeric scalar. The default is 9. +% boxAlpha - The transparency of the boxes (0 is +% transparent, 1 is opaque). The default is 1. +% boxColor - Fill color of the box. The setting can be a +% color specifier (3-element vector or single +% character), 'auto', 'none', or a handle to a +% colormap function (e.g. @gray); 'auto' means +% that Matlab's default colors are used. The +% default is 'none'. +% boxWidth - The width of the box. The setting can be +% 'auto' (meaning that the width is determined +% automatically) or a scalar (specifying the +% width in x-axis units). The default is +% 'auto'. +% groupLabelFontSize - Specify the font size of the group labels +% when the 'style' option is set to +% 'hierarchy'. The default is 9. +% groupLabelHeight - Specify the height of the area reserved for +% group labels when the 'style' option is set +% to 'hierarchy'. The height is determined +% automatically ('auto') or can be specified in +% scale units. The default is 'auto'. +% groupLabels - If the 'style' option is set to 'hierarchy' +% then these labels will be used to label the +% boxes for each x-group. The parameter should +% be specified as a cell vector whereby the Nth +% element contains a vector of length +% SIZE(Y,N+2). By default, the labels are +% empty. +% groupWidth - Specify the proportion of the x-axis interval +% across which each x-group of boxes should be +% spread. The default is 0.75. +% limit - Mode indicating the limits that define +% outliers. When set to '1.5IQR' or '3IQR', the +% min and max values are Q1-Z*IQR and Q3+Z*IQR, +% where Z = 1.5 or 3 respectively. When set to +% 'none', the min and max values are the min +% and max of the data (in this case there will +% be no outliers). The property may also be +% specified as a two-element vector determining +% the limits as percentiles (e.g. [5,95]). The +% default is '1.5IQR'. +% lineColor - Color of the box outline and whiskers. The +% default is 'k'. +% lineStyle - Style of the whisker line. The default is +% '-'. +% lineWidth - Width, in points, of the box outline, whisker +% lines, notch line, violin, and outlier marker +% edges. The default is 1. +% meanColor - Color of the mean marker when showMean=true. +% The default is 'auto' (see boxColor). +% meanMarker - Marker used for the mean when showMean=true. +% The default is '+'. +% meanSize - Size, in point units, of the mean markers +% when showMean=true. The default is 6. +% medianColor - Color of the median line. The default is +% 'auto' (see boxColor). +% method - The method used to calculate the quantiles, +% labelled according to +% http://en.wikipedia.org/wiki/Quantile. The +% default is 'R-8' whereas the default for +% Matlab is 'R-5'. See +% IOSR.STATISTICS.QUANTILE. +% notch - Logical value indicating whether the box +% should have a notch. The notch is centred on +% the median and extends to �1.58*IQR/sqrt(N), +% where N is the sample size (number of non-NaN +% rows in Y). Generally if the notches of two +% boxes do not overlap, this is evidence of a +% statistically significant difference between +% the medians. The default is false. +% notchDepth - Depth of the notch as a proportion of half +% the box width. The default is 0.4. +% notchLine - Logical value specifying whether to draw a +% horizontal line in the box at the extremes of +% the notch. (May be specified indpendently of +% 'notch'.) The default is false. +% notchLineColor - Color of the notch line when notchLine=true. +% The default is 'k'. +% notchLineStyle - Line style of the notch line when +% notchLine=true. The default is ':'. +% outlierSize - Size, in square points, of the outlier +% marker. The default is 36. +% percentile - Percentile limits of the boxes. The default +% is [25,75]. All other statistics, such as +% those that depend on the IQR (e.g. whisker +% extent and notch height), are unaffected by +% this parameter. +% sampleFontSize - Specify the font size of the sample size +% display (if sampleSize=true). The default is +% 9. +% sampleSize - Specify whether to display the sample size in +% the top-right of each box. The default is +% false. +% scaleWidth - Logical value to specify scaling the width of +% each box according to the square root of the +% sample size. The default is false. +% scatterAlpha - Set the transparency of the scatter markers +% (0 is transparent, 1 is opaque) when +% showScatter=true. The default is 1. +% scatterColor - Scatter marker color for scatter plots of +% underlying data (if showScatter=true). The +% default is [.5 .5 .5]. +% scatterLayer - Set the layer of scatter plots with respect +% to the boxes. Can be set to 'top' or +% 'bottom'. The default is 'top'. +% scatterMarker - Marker used for scatter plots of underlying +% data (if showScatter=true). The default is +% 'x'. +% scatterSize - Size, in square points, of the scatter +% markers (if showScatter=true). The default is +% 36. +% showLegend - Display a legend of the data. The labels can +% be set using the 'groupLabels' option. Note +% that the legend uses the box color, median +% line, or violin fill color to distinguish +% legend entries. If these properties do not +% differ between boxes then an error will be +% returned. +% showMean - Logical value determines whether to display +% the mean of the data for each box. The +% default is false. +% showOutliers - Logical value determines whether to display +% outliers. The default is true. +% showScatter - If set to true, a scatter plot of the +% underlying data for each box will be +% overlayed on the plot. The data will have a +% random x-axis offset with respect to the box +% centre. Data that are outliers are not +% included. The default is false. +% showViolin - If true, a 'violin' [1] kernel density +% outline of the data underlying each box will +% be plotted. The outline is calculated using +% the IOSR.STATISTICS.KERNELDENSITY function. +% The default is false. +% style - Determine whether to show additional x-axis +% labels for the data. If set to 'hierarchy', +% additional hierarchical x-axis labels will be +% added for the plot. The labels can be set +% using the 'groupLabels' option. If set to +% 'normal' (default) no additional labels will +% be plotted. +% symbolColor - Outlier marker color. The default is +% 'auto' (see boxColor). +% symbolMarker - Marker used to denote outliers. The default +% is 'o'. +% theme - Specify a display theme to change multiple +% display properties. The options are: +% 'colorall' : colored boxes (with 0.4 +% alpha), lines, and +% scatter markers (median +% line and mean marker are +% black) +% 'colorlines' : clear boxes, black mean +% markers, colored lines +% and scatter markers +% 'colorboxes' : colored boxes, black +% lines and markers, gray +% scatter markers +% 'default' : clear boxes, colored +% median lines and markers, +% gray scatter markers +% Use the 'themeColors' property to specify the +% color(s) that are used. +% themeColors Colors used when creating the theme. The +% default is 'auto' (see boxColor). +% violinBins - If 'showViolin' is true, this specifes the +% bins used to calculate the kernel density. +% See IOSR.STATISTICS.KERNELDENSITY. +% violinBinWidth - If 'showViolin' is true, this specifes the +% bin width used to calculate the kernel +% density. See IOSR.STATISTICS.KERNELDENSITY. +% violinColor - Fill color for the violins. The default is +% 'none' (see boxColor). +% violinKernel - If 'showViolin' is true, this specifes the +% kernel used to calculate the kernel density. +% See IOSR.STATISTICS.KERNELDENSITY. +% xSeparator - Logical value that when true adds a separator +% line between x groups. The default is false. +% xSpacing - Determine the x-axis spacing of boxes. By +% default ('x'), the data in x are used to +% determine the position of boxes on the x-axis +% (when x is numeric). Alternativley, when set +% to 'equal', boxes are equally-spaced, but the +% data in x are used to label the axis; the +% x-axis ticks are at 1:LENGTH(X). +% handles - Structure containing handles to the various +% objects that constitute the plot. The +% fields/handles are: +% 'axes' : the parent axes of +% the box plot +% 'fig' : the parent figure of +% the box plot +% 'addPrctiles' : chart line objects +% for each additional +% percentile marker +% 'addPrctilesTxt' : text objects for each +% additional percentile +% marker +% 'box' : patch objects for +% each box +% 'medianLines' : line objects for each +% median line +% 'means' : chart line objects +% for each mean marker +% 'notchLowerLines' : line objects for each +% lower notch line +% 'notchUpperLines' : line objects for each +% upper notch line +% 'upperWhiskers' : line objects for each +% upper whisker line +% 'lowerWhiskers' : line objects for each +% lower whisker line +% 'upperWhiskerTips': line objects for each +% upper whisker tip +% 'lowerWhiskerTips': line objects for each +% lower whisker line +% 'outliers' : scatter objects for +% each set of outliers +% 'scatters' : scatter objects for +% each scatter overlay +% 'samplesTxt' : text objects for each +% sample size display +% 'groupsTxt' : text objects for each +% group label +% 'xseps' : line objects for each +% x separator +% 'legend' : the legend object +% +% These properties can be referenced using dot notation - e.g. H.BOXCOLOR +% where H is an instance of the BOXPLOT object - or using the SET and GET +% methods - e.g. GET(H,'BOXCOLOR'). Both methods are case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% Read-only properties: +% x - The x data. +% y - The y data. +% weights - Array giving the weights for the data in y. +% The array must be the same size as y. This +% option may be specified in the constructor. +% statistics - Structure containing the statistics used +% for the box plot. With the exception of +% 'outliers', 'outliers_IX', 'addPrctiles', and +% 'percentile' noted below, each field contains +% a 1-by-P-by-G-by-I-by-J... numeric array of +% values (identical to that returned by +% IOSR.STATISTICS.QUANTILE). The fields are: +% 'addPrctiles' : an A-by-P-by-G... array +% containing the +% additional percentile +% values specified by the +% 'addPrctiles' property, +% where A is the number +% of percentiles in the +% property +% 'percentile' : the percentile limits +% specified by the +% 'percentile' property +% 'median' : the median values +% 'N' : the sample size +% 'PL' : the lower percentiles +% specified by the +% 'percentile' property, +% and the lower limit of +% the boxes (default is +% 25th percentile) +% 'PU' : the upper percentiles +% specified by the +% 'percentile' property, +% and the upper limit of +% the boxes (default is +% 75th percentile) +% 'Q1' : the 25th percentiles +% 'Q3' : the 75th percentiles +% 'IQR' : the inter-quartile +% ranges +% 'mean' : the mean values +% 'min' : the minimum values +% (excl. outliers) +% 'max' : the maximum values +% (excl. outliers) +% 'notch_u' : the upper notch values +% 'notch_l' : the lower notch values +% 'outliers' : a 1-by-P-by-G cell +% array of outlier values +% 'outliers_IX' : a logical array, the +% same size as Y, with +% true values indicating +% outliers +% 'std' : the standard deviations +% +% In addition to the above specifications, some options can be specified +% for each group. Parameters should be specified as a cell array of size +% G-by-I-by-J... . These options are: 'boxColor', 'lineColor', +% 'lineStyle', 'meanColor', 'meanMarker, 'medianColor', 'notchLineColor', +% 'notchLineStyle', 'scatterMarker', 'scatterColor', 'symbolColor', +% 'symbolMarker', 'themeColor', and 'violinColor'. +% +% As noted above, colors may be specified as a colormap function handle +% (e.g. @gray for grayscale colors). The function handle can refer to one +% of the built-in colormap functions, or any other function capable of +% generating valid colormaps. If the specified colormap is one of the +% built-in colormaps 'hot' (@hot), 'gray' (@gray), 'bone' (@bone), +% 'copper' (@copper), or 'pink' (@pink), then boxPlot will take steps to +% try to restrict the range of colors. Specifically, for fills (e.g. +% 'boxColor'), the colors will be restricted such that the minimum +% luminance is 0.33 (in order to not mask dark lines). For lines, the +% colors will be restricted such that the maximum luminance is 0.66 (in +% order that lines are not masked by the white background). +% +% IOSR.STATISTICS.BOXPLOT methods: +% boxPlot - Create the box plot. +% +% See also IOSR.STATISTICS.TAB2BOX, IOSR.STATISTICS.QUANTILE, COLORMAP, +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT, +% IOSR.STATISTICS.FUNCTIONALBOXPLOT, IOSR.STATISTICS.KERNELDENSITY. +% +% References +% +% [1] Hintze, Jerry L.; Nelson, Ray D. (1998). "Violin Plots: A Box +% Plot-Density Trace Synergism". The American Statistician. 52 (2): +% 181?4. + +% Copyright 2016 University of Surrey. + + properties (AbortSet) + addPrctiles = [] % Additional percentiles to plot. + addPrctilesColors % Colors for the additional percentile markers. + addPrctilesLabels = {} % Labels for additional percentiles. + addPrctilesMarkers = {} % Markers for additional percentiles. + addPrctilesSize % Size of the additional percentile markers. + addPrctilesTxtSize % Size of the additional percentile labels text. + boxAlpha = 1 % The transparency of the boxes. + boxColor = 'none' % Fill color of the boxes. + boxWidth = 'auto' % The width of the boxes. + groupLabelFontSize = 9 % The font size of the group labels. + groupLabelHeight = 'auto' % The height of the area reserved for group labels. + groupLabels = [] % Labels used to label the boxes for each x-group. + groupWidth = 0.75 % The proportion of the x-axis interval across which each x-group of boxes should be spread. + limit = '1.5IQR' % Mode indicating the limits that define outliers. + lineColor = 'k' % Color of the box outlines and whiskers. + lineStyle = '-' % Style of the whisker lines. + lineWidth = 1 % Width, in points, of the box outline, whisker lines, notch line, and outlier marker edges. + meanColor = 'auto' % Color of the mean marker. + meanMarker = '+' % Marker used for the mean. + meanSize = 6 % Size, in point units, of the mean markers. + medianColor = 'auto' % Color of the median line. + method = 'R-8' % The method used to calculate the quantiles. + notch = false % Whether the box should have a notch. + notchDepth = 0.4 % Depth of the notch as a proportion of half the box width. + notchLineColor = 'k' % Color of the notch line. + notchLineStyle = ':' % Line style of the notch line. + notchLine = false % Whether to draw a horizontal line in the box at the extremes of the notch. + outlierSize = 6^2 % Size, in square points, of the outlier markers. + percentile = [25,75] % Percentile limits of the box. + sampleFontSize = 9 % Specify the font size of the sample size display. + sampleSize = false % Whether to display the sample size in the top-right of each box. + scaleWidth = false % Scale the width of each box according to the square root of the sample size. + scatterAlpha = 1 % The transparency of the scatter markers. + scatterColor = [.5 .5 .5] % Scatter marker color for scatter plots of underlying data. + scatterLayer = 'top' % The layer of scatter plots with respect to the boxes. + scatterMarker = 'x' % Marker used for scatter plots of underlying data. + scatterSize = 6^2 % Size, in square points, of the scatter markers. + showLegend = false % Draw a legend. + showMean = false % Display the mean of the data for each box. + showOutliers = true % Display outliers. + showScatter = false % Display a scatter plot of the underlying data for each box. + showViolin = false % Display a violin (kernel density) plot for the underlying data. + style = 'normal' % Determine whether to show additional x-axis labels for the data. + symbolColor = 'auto' % Outlier marker color. + symbolMarker = 'o' % Marker used to denote outliers. + theme = 'default' % Control a range of display properties. + themeColors = 'auto' % Colors used when creating the theme. + violinBins = 'auto' % The bins used to calculate the violins. + violinBinWidth = 'auto' % The width of the bins used to calculate the violins. + violinAlpha = 1 % Alpha of the violins. + violinColor = 'none' % Color of the violins. + violinWidth = 'auto' % The width of the violins. + violinKernel = 'normal' % The violin kernel used to calculate the kernel density. + xSeparator = false % Add a separator line between x groups. + xSpacing = 'x' % Determine the x-axis spacing of boxes. + end + + properties (Access = private) + diffx % smallest difference of x axis data + groupXticks % x ticks for every box + groupDims % dimensions of data for each x group + groupRange % scale value range of each x group + xlabels % labels for the x axis + xticks % x-axis tick points + end + + properties (SetAccess = private, Dependent, Hidden) + addPrctilesHandle = [] % Chart line objects objects for the additional percentiles markers. + addPrctilesTxtHandle = [] % Text objects for each additional percentile label. + boxHandles = [] % Patch objects for each box. + mLineHandles = [] % Line objects for each median line. + meanHandles = [] % Chart line objects for each mean marker. + notchLowerLineHandles = [] % Line objects for each lower notch line. + notchUpperLineHandles = [] % Line objects for each upper notch line. + upperWhiskerHandles = [] % Line objects for each upper whisker line. + lowerWhiskerHandles = [] % Line objects for each lower whisker line. + upperWhiskerTipHandles = [] % Line objects for each upper whisker tip. + lowerWhiskerTipHandles = [] % Line objects for each lower whisker tip. + outliersHandles = [] % Scatter objects for each set of outliers. + scatterHandles = [] % Scatter objects for each scatter overlay. + sampleTxtHandes = [] % Text objects for each sample size display. + groupTxtHandes = [] % Text objects for each group label. + xsepHandles = [] % Line objects for each x separator. + legendHandle = [] % Legend object. + end + + methods + + function obj = boxPlot(varargin) + % BOXPLOT Draw a box plot. + % + % IOSR.STATISTICS.BOXPLOT(Y) produces a box plot of the data in + % Y. If Y is a vector, there is just one box. If Y is a matrix, + % there is one box per column. If Y is an + % N-by-P-by-G-by-I-by-J... array then G*I*J*... boxes are plotted + % hierarchically for each column P; i.e. J boxes are plotted for + % each index of I, and J*I boxes are plotted for each index of G. + % For each box, the central mark is the median of the + % data/column, the edges of the box are the 25th and 75th + % percentiles, the whiskers extend to the most extreme data + % points not considered outliers, and outliers are plotted + % individually. NaNs are excluded from the data. + % + % Tabular data can be arranged into the appropriate format using + % the IOSR.STATISTICS.TAB2BOX function. + % + % IOSR.STATISTICS.BOXPLOT(X,Y) specifies the x-axis values for + % each box. X should be a vector, with as many elements as Y has + % columns. The default is 1:SIZE(Y,2). + % + % IOSR.STATISTICS.BOXPLOT(...,'PARAMETER',VALUE) allows the + % plotting options to be specified when the plot is constructed. + % + % IOSR.STATISTICS.BOXPLOT(AX,...) creates the box plot in the + % axes specified by AX. + % + % Examples + % + % Example 1: Basic grouped box plot with legend + % + % y = randn(50,3,3); + % x = [1 2 3.5]; + % y(1:25) = NaN; + % + % figure; + % h = iosr.statistics.boxPlot(x,y,... + % 'symbolColor','k',... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor',{[1 0 0]; [0 1 0]; [0 0 1]},... + % 'groupLabels',{'y1','y2','y3'},... + % 'showLegend',true); + % box on + % + % Example 2: Grouped box plot with overlayed data + % + % figure; + % iosr.statistics.boxPlot(x,y,... + % 'symbolColor','k',... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor','auto',... + % 'showScatter',true); + % box on + % + % Example 3: Grouped box plot with displayed sample sizes + % and variable widths + % + % figure; + % iosr.statistics.boxPlot(x,y,... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor','auto',... + % 'sampleSize',true,... + % 'scaleWidth',true); + % box on + % + % Example 4: Grouped notched box plot with x separators and + % hierarchical labels + % + % figure; + % iosr.statistics.boxPlot({'A','B','C'},y,... + % 'notch',true,... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor','auto',... + % 'style','hierarchy',... + % 'xSeparator',true,... + % 'groupLabels',{{'Group 1','Group 2','Group 3'}}); + % box on + % + % Example 5: Box plot with legend labels from data + % + % % load data + % % (requires Statistics or Machine Learning Toolbox) + % load carbig + % + % % arrange data + % [y,x,g] = iosr.statistics.tab2box(Cylinders,MPG,when); + % + % % sort + % IX = [1 3 2]; % order + % g = g{1}(IX); + % y = y(:,:,IX); + % + % % plot + % figure + % h = iosr.statistics.boxPlot(x,y,... + % 'symbolColor','k','medianColor','k','symbolMarker','+',... + % 'boxcolor',{[1 1 1],[.75 .75 .75],[.5 .5 .5]},... + % 'scalewidth',true,'xseparator',true,... + % 'groupLabels',g,'showLegend',true); + % box on + % title('MPG by number of cylinders and period') + % xlabel('Number of cylinders') + % ylabel('MPG') + % + % Example 6: Box plot calculated from weighted quantiles + % + % % load data + % load carbig + % + % % random weights + % weights = rand(size(MPG)); + % + % % arrange data + % [y,x,g] = iosr.statistics.tab2box(Cylinders,MPG,when); + % weights_boxed = iosr.statistics.tab2box(Cylinders,weights,when); + % + % % plot + % figure + % h = iosr.statistics.boxPlot(x,y,'weights',weights_boxed); + % + % Example 7: Draw a violin plot + % y = randn(50,3,3); + % x = [1 2 3.5]; + % y(1:25) = NaN; + % figure('color','w'); + % h2 = iosr.statistics.boxPlot(x,y, 'showViolin', true, 'boxWidth', 0.025, 'showOutliers', false); + % box on + + if nargin > 0 + + %% check for deprecated properties + + % check for scatter option + scatterIX = strcmpi('scatter',varargin); + if any(scatterIX) + warning('The ''scatter'' property is deprecated. Use ''showScatter'' instead.'); + varargin{scatterIX} = 'showScatter'; + end + + % check for mean option + meanIX = strcmpi('mean',varargin); + if any(meanIX) + warning('The ''mean'' property is deprecated. Use ''showMean'' instead.'); + varargin{meanIX} = 'showMean'; + end + + %% set x, y, and dims + + % check for input data + start = obj.getXY(varargin{:}); + obj.groupDims = obj.ydims(3:end); + + % create initial theme + obj.createTheme(); + + % check weights + obj.checkWeights(); + + % set properties from varargin + obj.setProperties(start,nargin,varargin); + + % remove NaN columns + obj.removeNaN(); + + % set x axis properties and labels + obj.setXprops(); + + %% statistics + + % calculate statistics + obj.calculateStats(); + + %% draw + + % set handles + obj.parseAxesHandle(varargin{:}); + + % draw the box plot + obj.draw('all'); + + % add listener to ylim so that some properties can be redrawn + addlistener(handle(obj.handles.axes),'YLim','PostSet',... + @(hProp,eventData) obj.eventHandler(hProp,eventData)); + + end + + end + + %% dependent handle getters + + % these are all deprecated and the handles moved to the obj.handles struct + + function val = get.addPrctilesHandle(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.addPrctilesHandle'' is deprecated. Use ''obj.handles.addPrctiles'' instead.'); + val = obj.handles.addPrctiles; + end + + function val = get.addPrctilesTxtHandle(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.addPrctilesTxtHandle'' is deprecated. Use ''obj.handles.addPrctilesTxt'' instead.'); + val = obj.handles.addPrctilesTxt; + end + + function val = get.boxHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.boxHandles'' is deprecated. Use ''obj.handles.box'' instead.'); + val = obj.handles.box; + end + + function val = get.mLineHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.mLineHandles'' is deprecated. Use ''obj.handles.medianLines'' instead.'); + val = obj.handles.medianLines; + end + + function val = get.meanHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.meanHandles'' is deprecated. Use ''obj.handles.means'' instead.'); + val = obj.handles.means; + end + + function val = get.notchLowerLineHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.notchLowerLineHandles'' is deprecated. Use ''obj.handles.notchLowerLines'' instead.'); + val = obj.handles.notchLowerLines; + end + + function val = get.notchUpperLineHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.notchUpperLineHandles'' is deprecated. Use ''obj.handles.notchUpperLines'' instead.'); + val = obj.handles.notchUpperLines; + end + + function val = get.upperWhiskerHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.upperWhiskerHandles'' is deprecated. Use ''obj.handles.upperWhiskers'' instead.'); + val = obj.handles.upperWhiskers; + end + + function val = get.lowerWhiskerHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.lowerWhiskerHandles'' is deprecated. Use ''obj.handles.lowerWhiskers'' instead.'); + val = obj.handles.lowerWhiskers; + end + + function val = get.upperWhiskerTipHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.upperWhiskerTipHandles'' is deprecated. Use ''obj.handles.upperWhiskerTips'' instead.'); + val = obj.handles.upperWhiskerTips; + end + + function val = get.lowerWhiskerTipHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.lowerWhiskerTipHandles'' is deprecated. Use ''obj.handles.lowerWhiskerTips'' instead.'); + val = obj.handles.lowerWhiskerTips; + end + + function val = get.outliersHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.outliersHandles'' is deprecated. Use ''obj.handles.outliers'' instead.'); + val = obj.handles.outliers; + end + + function val = get.scatterHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.scatterHandles'' is deprecated. Use ''obj.handles.scatters'' instead.'); + val = obj.handles.scatters; + end + + function val = get.sampleTxtHandes(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.sampleTxtHandes'' is deprecated. Use ''obj.handles.samplesTxt'' instead.'); + val = obj.handles.samplesTxt; + end + + function val = get.groupTxtHandes(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.groupTxtHandes'' is deprecated. Use ''obj.handles.groupsTxt'' instead.'); + val = obj.handles.groupsTxt; + end + + function val = get.xsepHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.xsepHandles'' is deprecated. Use ''obj.handles.xseps'' instead.'); + val = obj.handles.xseps; + end + + function val = get.legendHandle(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.legendHandle'' is deprecated. Use ''obj.handles.legend'' instead.'); + val = obj.handles.legend; + end + + %% accessor functions + + % set/get additional percentiles + + function val = get.addPrctiles(obj) + val = obj.addPrctiles; + end + + function set.addPrctiles(obj,val) + if ~isempty(val) + assert(isvector(val) && isnumeric(val), 'iosr:boxPlot:addPrctilesVector', '''ADDPRCTILES'' should be a numeric vector') + assert(all(val<=100) && all(val>=0), 'iosr:boxPlot:addPrctilesRange', '''ADDPRCTILES'' values should be in the interval [0,100].') + end + obj.addPrctiles = val; + obj.calculateStats(); + obj.draw('addPrctiles'); + end + + % set/get additional percentiles colors + + function val = get.addPrctilesColors(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesColors,{'k'}); + end + + function set.addPrctilesColors(obj,val) + if ~isempty(val) + assert(iscell(val), 'iosr:boxPlot:addPrctilesColors', '''ADDPRCTILESCOLORS'' should be a cell array') + end + obj.addPrctilesColors = val; + obj.draw(); + end + + % set/get additional percentiles labels + + function val = get.addPrctilesLabels(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesLabels,{''}); + end + + function set.addPrctilesLabels(obj,val) + if ~isempty(val) + assert(iscellstr(val), 'iosr:boxPlot:addPrctilesLabels', '''ADDPRCTILESLABELS'' should be a cell array of strings') + end + obj.addPrctilesLabels = val; + obj.draw(); + end + + % set/get additional percentiles markers + + function val = get.addPrctilesMarkers(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesMarkers,{'*'}); + end + + function set.addPrctilesMarkers(obj,val) + if ~isempty(val) + assert(iscellstr(val), 'iosr:boxPlot:addPrctilesMarkers', '''ADDPRCTILESMARKERS'' should be a cell array of strings') + end + obj.addPrctilesMarkers = val; + obj.draw(); + end + + % set/get additional percentiles marker size + + function val = get.addPrctilesSize(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesSize,6); + end + + function set.addPrctilesSize(obj,val) + if ~isempty(val) + assert(isnumeric(val) && isvector(val), 'iosr:boxPlot:addPrctilesSize', '''ADDPRCTILESSIZE'' should be a numeric vector') + end + obj.addPrctilesSize = val; + obj.draw(); + end + + % set additional percentiles label font size + + function set.addPrctilesTxtSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:addPrctilesTxtSize', '''ADDPRCTILESTXTSIZE'' should be a numeric scalar') + obj.addPrctilesTxtSize = val; + obj.draw(); + end + + % set box alpha + + function set.boxAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:boxAlpha', '''BOXALPHA'' must be a numeric scalar') + obj.boxAlpha = val; + obj.draw('legend'); + end + + % set/get box color + + function val = get.boxColor(obj) + val = obj.checkColor(obj.boxColor,'fill'); + val = obj.groupOption(val,'boxColor'); + end + + function set.boxColor(obj,val) + obj.boxColor = val; + obj.draw('legend'); + end + + % set box width + + function set.boxWidth(obj,val) + assert((isnumeric(val) && isscalar(val)) || strcmpi(val,'auto'), 'iosr:boxPlot:boxWidth', '''BOXWIDTH'' must be a numeric scalar or ''auto''.') + obj.boxWidth = val; + obj.draw('all'); + end + + % set/get group labels + + function val = get.groupLabels(obj) + if prod(obj.groupDims)==numel(obj.groupLabels) && numel(obj.groupLabels)>1 + val = {obj.groupLabels}; + else + val = obj.groupLabels; + end + if ~isempty(val) % use input + assert(isvector(val) && iscell(val),... + 'iosr:boxPlot:groupLabelsType', ... + 'The GROUPLABELS option should be a cell vector'); + valSize = cellfun(@length,val); + assert(prod(obj.outDims(3:end))==prod(valSize), ... + 'iosr:boxPlot:groupLabelsSize', ... + ['The GROUPLABELS option should be a cell vector; ' ... + 'the Nth element should contain a vector of length SIZE(Y,N+2)']) + assert(isequal(obj.outDims(3:end),valSize(1:length(obj.outDims)-2)), ... + 'iosr:boxPlot:groupLabelsSize', ... + ['The GROUPLABELS option should be a cell vector; ' ... + 'the Nth element should contain a vector of length SIZE(Y,N+2)']) + else % create placeholder labels + val = cell(1,length(obj.groupDims)); + c = 1; + for m = 1:length(val) + val{m} = cell(1,obj.groupDims(m)); + for n = 1:obj.groupDims(m) + val{m}{n} = sprintf('Data %d',c); + c = c+1; + end + end + end + end + + function set.groupLabels(obj,val) + obj.groupLabels = val; + obj.draw('style','legend'); + end + + % set group label font size + + function set.groupLabelFontSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:groupLabelsFontSize', '''GROUPLABELFONTSIZE'' must be a numeric scalar.') + obj.groupLabelFontSize = val; + obj.draw(); + end + + % set group label height + + function set.groupLabelHeight(obj,val) + assert(strcmp(val,'auto') || (isnumeric(val) && isscalar(val)), 'iosr:boxPlot:groupLabelHeight', '''GROUPLABELHEIGHT'' must be ''auto'' or a numeric scalar.') + obj.groupLabelHeight = val; + obj.draw('style'); + end + + % set group width + + function set.groupWidth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:groupWidth', '''GROUPWIDTH'' must be a numeric scalar') + obj.groupWidth = val; + obj.setXprops(); + obj.draw('all'); + end + + % set stats limit + + function set.limit(obj,val) + if isnumeric(val) + assert(isnumeric(val) && numel(val)==2, 'iosr:boxPlot:limitSize', '''LIMIT'' must be a two-element numeric vector.') + assert(all(val<=100) && all(val>=0), 'iosr:boxPlot:limitRange', '''LIMIT'' values should be in the interval [0,100].') + if all(val<1) + warning('iosr:boxPlot:limitRange','''LIMIT'' values should be in the interval [0,100].') + end + else + assert(ischar(val), 'iosr:boxPlot:limitType', '''LIMIT'' must be a char or numeric array.') + assert(any(strcmpi(val,{'1.5IQR','3IQR','none'})), 'iosr:boxPlot:limitUnknownOption', '''LIMIT'' parameter not recognised.') + end + obj.limit = val; + obj.calculateStats(); + obj.draw('whiskers','outliers','scatter'); + end + + % get/set line colors + + function val = get.lineColor(obj) + val = obj.checkColor(obj.lineColor,'line'); + val = obj.groupOption(val,'lineColor'); + end + + function set.lineColor(obj,val) + obj.lineColor = val; + obj.draw('legend'); + end + + % get/set line style + + function val = get.lineStyle(obj) + val = obj.groupOption(obj.lineStyle,'lineStyle'); + end + + function set.lineStyle(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:lineStyle', '''LINESTYLE'' must be a char array or cell array of strings.') + obj.lineStyle = val; + obj.draw('legend'); + end + + % set line width + + function set.lineWidth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:lineWidth', '''LINEWIDTH'' must be a numeric scalar.') + obj.lineWidth = val; + obj.draw('all'); + end + + % get/set mean color + + function val = get.meanColor(obj) + val = obj.checkColor(obj.meanColor,'line'); + val = obj.groupOption(val,'meanColor'); + end + + function set.meanColor(obj,val) + obj.meanColor = val; + obj.draw(); + end + + % get/set mean marker + + function val = get.meanMarker(obj) + val = obj.groupOption(obj.meanMarker,'meanMarker'); + end + + function set.meanMarker(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:meanMarker', '''MEANMARKER'' must be a char array or cell array of strings.') + obj.meanMarker = val; + obj.draw(); + end + + % set mean size + + function set.meanSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:meanSize', '''MEANSIZE'' must be a numeric scalar.') + obj.meanSize = val; + obj.draw(); + end + + % get/set median color + + function val = get.medianColor(obj) + val = obj.checkColor(obj.medianColor,'line'); + val = obj.groupOption(val,'medianColor'); + end + + function set.medianColor(obj,val) + obj.medianColor = val; + obj.draw('legend'); + end + + % set stats method + + function set.method(obj,val) + assert(ischar(val), 'iosr:boxPlot:method', '''METHOD'' must be a char array.') + obj.method = val; + obj.calculateStats(); + obj.draw('all'); + end + + % set notch + + function set.notch(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:notch', '''NOTCH'' must be logical.') + obj.notch = val; + obj.draw('boxes'); + end + + % set notch depth + + function set.notchDepth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:notchDepth', '''NOTCHDEPTH'' must be a numeric scalar') + obj.notchDepth = val; + obj.draw('boxes'); + end + + % get/set notch line color + + function val = get.notchLineColor(obj) + val = obj.checkColor(obj.notchLineColor,'line'); + val = obj.groupOption(val,'notchLineColor'); + end + + function set.notchLineColor(obj,val) + obj.notchLineColor = val; + obj.draw(); + end + + % get/set notch line style + + function val = get.notchLineStyle(obj) + val = obj.groupOption(obj.notchLineStyle,'notchLineStyle'); + end + + function set.notchLineStyle(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:notchLineStyle', '''NOTCHLINESTYLE'' must be a char array or cell array of strings.') + obj.notchLineStyle = val; + obj.draw(); + end + + % set notch line + + function set.notchLine(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:notchLine', '''NOTCHLINE'' must be logical.') + obj.notchLine = val; + obj.draw('boxes'); + end + + % set outlier size + + function set.outlierSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:outlierSize', '''OUTLIERSIZE'' must be a numeric scalar.') + obj.outlierSize = val; + obj.draw(); + end + + % set percentile + + function set.percentile(obj,val) + assert(isnumeric(val) && numel(val)==2, 'iosr:boxPlot:percentileSize', '''PERCENTILE'' must be a two-element numeric vector.') + assert(all(val<=100) && all(val>=0), 'iosr:boxPlot:percentileRange', '''PERCENTILE'' values should be in the interval [0,100].') + if all(val<1) + warning('iosr:boxPlot:percentileRange', '''PERCENTILE'' values should be in the interval [0,100].') + end + obj.percentile = val; + obj.calculateStats(); + obj.draw('all'); + end + + % set sample font size + + function set.sampleFontSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:sampleFontSize', '''SAMPLEFONTSIZE'' must be a numeric scalar.') + obj.sampleFontSize = val; + obj.draw(); + end + + % set sample size option + + function set.sampleSize(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:sampleSize', '''SAMPLESIZE'' must be logical.') + obj.sampleSize = val; + obj.draw('boxes'); + end + + % set scale width option + + function set.scaleWidth(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:scaleWidth', '''SCALEWIDTH'' must be logical.') + obj.scaleWidth = val; + obj.draw('boxes','scatter','outliers'); + end + + % set legend + + function set.showLegend(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showLegend', '''SHOWLEGEND'' must be logical.') + obj.showLegend = val; + obj.draw('legend'); + end + + % set show mean option + + function set.showMean(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showMean', '''SHOWMEAN'' must be logical.') + obj.showMean = val; + obj.draw('means'); + end + + % set show outliers option + + function set.showOutliers(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showOutliers', '''SHOWOUTLIERS'' must be logical.') + obj.showOutliers = val; + obj.draw('outliers'); + end + + % set show scatter option + + function set.showScatter(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showScatter', '''SHOWSCATTER'' must be logical.') + obj.showScatter = val; + obj.draw('scatter'); + end + + % set scatter alpha + + function set.scatterAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:scatterAlpha', '''SCATTERALPHA'' must be a numeric scalar') + obj.scatterAlpha = val; + obj.draw(); + end + + % get/set scatter color + + function val = get.scatterColor(obj) + val = obj.checkColor(obj.scatterColor,'line'); + val = obj.groupOption(val,'scatterColor'); + end + + function set.scatterColor(obj,val) + obj.scatterColor = val; + obj.draw(); + end + + % set scatter layer + + function set.scatterLayer(obj,val) + assert(ischar(val), 'iosr:boxPlot:scatterLayer', '''SCATTERLAYER'' must be a char array.') + obj.scatterLayer = val; + obj.draw(); + end + + % get/set scatter marker + + function val = get.scatterMarker(obj) + val = obj.groupOption(obj.scatterMarker,'scatterMarker'); + end + + function set.scatterMarker(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:scatterMarker', '''SCATTERMARKER'' must be a char array or cell array of strings.') + obj.scatterMarker = val; + obj.draw(); + end + + % set scatter marker size + + function set.scatterSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:scatterSize', '''SCATTERSIZE'' must be a numeric scalar.') + obj.scatterSize = val; + obj.draw(); + end + + % violin + + function set.showViolin(obj,val) + assert(islogical(val) && isscalar(val), 'iosr:boxPlot:showViolin', '''VIOLIN'' must be logical.') + obj.showViolin = val; + obj.draw('violin','whiskers'); + end + + % set style + + function set.style(obj,val) + assert(ischar(val), 'iosr:boxPlot:styleType', '''STYLE'' must be a char array.') + assert(any(strcmpi(val,{'normal','hierarchy'})), 'iosr:boxPlot:styleOption', '''STYLE'' must be either ''normal'' or ''hierarchy''.') + obj.style = val; + obj.draw('style'); + end + + % get/set outlier symbol color + + function val = get.symbolColor(obj) + val = obj.checkColor(obj.symbolColor,'line'); + val = obj.groupOption(val,'symbolColor'); + end + + function set.symbolColor(obj,val) + obj.symbolColor = val; + obj.draw(); + end + + % get/set outlier symbol marker + + function val = get.symbolMarker(obj) + val = obj.groupOption(obj.symbolMarker,'symbolMarker'); + end + + function set.symbolMarker(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:symbolMarker', '''SYMBOLMARKER'' must be a char array or cell array of strings.') + obj.symbolMarker = val; + obj.draw(); + end + + % set theme + + function set.theme(obj,val) + assert(ischar(val), 'iosr:boxPlot:theme', '''THEME'' must be a char array.') + obj.theme = val; + obj.createTheme(); + obj.draw('legend'); + end + + % theme color + + function val = get.themeColors(obj) + switch lower(obj.theme) + case {'graylines', 'colorlines', 'default'} + val = obj.checkColor(obj.themeColors,'lines'); + case {'grayboxes', 'colorall', 'colorboxes'} + val = obj.checkColor(obj.themeColors,'fill'); + end + val = obj.groupOption(val,'themeColors'); + end + + function set.themeColors(obj,val) + obj.themeColors = val; + obj.createTheme(); + obj.draw('all'); + end + + % set violin props + + function set.violinBins(obj,val) + assert(isnumeric(val) || strcmpi(val,'auto'), 'iosr:boxPlot:violinBins', '''VIOLINBINS'' must be numeric or ''auto''.') + obj.violinBins = val; + obj.draw('violin','whiskers'); + end + + function set.violinBinWidth(obj,val) + assert((isnumeric(val) && isscalar(val)) || strcmpi(val,'auto'), 'iosr:boxPlot:violinBinWidth', '''VIOLINBINWIDTH'' must be a numeric scalar or ''auto''.') + obj.violinBinWidth = val; + obj.draw('violin','whiskers'); + end + + function set.violinKernel(obj,val) + assert(ischar(val), 'iosr:boxPlot:violinKernel', '''VIOLINKERNEL'' must be a string.') + obj.violinKernel = val; + obj.draw('violin','whiskers'); + end + + function set.violinAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:violinAlpha', '''VIOLINALPHA'' must be a numeric scalar') + obj.violinAlpha = val; + obj.draw('legend'); + end + + function val = get.violinColor(obj) + val = obj.checkColor(obj.violinColor,'fill'); + val = obj.groupOption(val,'violinColor'); + end + + function set.violinColor(obj,val) + obj.violinColor = val; + obj.draw('legend'); + end + + function set.violinWidth(obj,val) + assert((isnumeric(val) && isscalar(val)) || strcmpi(val,'auto'), 'iosr:boxPlot:violinWidth', '''VIOLINWIDTH'' must be a numeric scalar or ''auto''.') + obj.violinWidth = val; + obj.draw('violin','whiskers'); + end + + % set x separator option + + function set.xSeparator(obj,val) + assert(islogical(val) && isscalar(val), 'iosr:boxPlot:xSeparator', '''XSEPARATOR'' must be logical.') + obj.xSeparator = val; + obj.draw('xsep'); + end + + % set x spacing option + + function set.xSpacing(obj,val) + assert(any(strcmpi(val,{'x','equal'})), 'iosr:boxPlot:xSpacing', '''XSPACING'' parameter not recognised.') + obj.xSpacing = val; + obj.setXprops(); + obj.draw('all'); + end + + + end + + methods (Access = protected) + + function draw(obj,varargin) + %DRAW main draw function + + if isfield(obj.handles,'axes') + subidx = cell(1,length(obj.outDims)); + hold on; + for n = 1:prod(obj.outDims) + % get indices + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = [{':'} subidx(2:end)]; + gidx = subidx(3:end); + + % determine where to put tick marks for group labels + obj.groupXticks(subidx{:}) = obj.xticks(subidx{2})+obj.getOffset(subidx); + + % plot individual components + if any(strcmpi('violin',varargin)) || any(strcmpi('all',varargin)) + obj.drawViolin(subidx,subidxAll); + end + if any(strcmpi('boxes',varargin)) || any(strcmpi('all',varargin)) + obj.drawBox(subidx,subidxAll); + end + if any(strcmpi('whiskers',varargin)) || any(strcmpi('all',varargin)) + obj.drawWhiskers(subidx); + end + if any(strcmpi('outliers',varargin)) || any(strcmpi('all',varargin)) + obj.drawOutliers(subidx); + end + if any(strcmpi('scatter',varargin)) || any(strcmpi('all',varargin)) + obj.drawScatter(subidx,gidx,subidxAll); + end + if any(strcmpi('means',varargin)) || any(strcmpi('all',varargin)) + obj.drawMean(subidx); + end + if any(strcmpi('addPrctiles',varargin)) || any(strcmpi('all',varargin)) + obj.drawAddPrctiles(subidx); + end + % change graphics options + obj.drawGroupGraphics(subidx,gidx); + end + % style things + if any(strcmpi('xsep',varargin)) || any(strcmpi('all',varargin)) + obj.drawXsepatator(); + end + if any(strcmpi('style',varargin)) || any(strcmpi('all',varargin)) + obj.drawStyle(); + end + if any(strcmpi('legend',varargin)) || any(strcmpi('all',varargin)) + obj.drawLegend(); + end + % change graphics options + obj.drawGlobalGraphics(); + % set layering + if isfield(obj.handles,'scatters') + uistack(obj.handles.scatters(:),obj.scatterLayer); + end + if isfield(obj.handles,'samplesTxt') + uistack(obj.handles.samplesTxt(:),'top'); + end + if isfield(obj.handles,'means') + uistack(obj.handles.means(:),'top'); + end + if isfield(obj.handles,'addPrctiles') + uistack(obj.handles.addPrctiles(:),'top'); + end + if isfield(obj.handles,'addPrctilesTxt') + uistack(obj.handles.addPrctilesTxt(:),'top'); + end + hold off; + end + end + + function drawViolin(obj,subidx,subidxAll) + %DRAWVIOLIN Draw the violin + + try % to delete the handles first + delete(obj.handles.violin(subidx{:})); + catch + end + + if obj.showViolin + + vBinWidth = obj.replaceAuto(... + obj.violinBinWidth, ... + [], ... + 'Unknown ''VIOLINBINWIDTH'' parameter.'); + + vBins = obj.replaceAuto(... + obj.violinBins, ... + [], ... + 'Unknown ''VIOLINBINS'' parameter.'); + + [d, xd] = iosr.statistics.kernelDensity(obj.y(subidxAll{:}), vBins, vBinWidth, obj.violinKernel); + halfviolinwidth = obj.calcHalfViolinWidth(subidx); + d = halfviolinwidth .* (d ./ max(d)); + obj.handles.violin(subidx{:}) = patch(... + [d; -flipud(d)] + obj.xticks(subidx{2}) + obj.getOffset(subidx), ... + [xd; flipud(xd)],'w','Parent',obj.handles.axes); + + end + + end + + function drawBox(obj,subidx,subidxAll) + %DRAWBOX draw boxes + + try % to delete the handles first + delete(obj.handles.box(subidx{:})); + catch + end + try + delete(obj.handles.medianLines(subidx{:})); + catch + end + try + delete(obj.handles.notchUpperLines(subidx{:})); + catch + end + try + delete(obj.handles.notchLowerLines(subidx{:})); + catch + end + try + delete(obj.handles.samplesTxt(subidx{:})); + catch + end + + % determine half box width + [~, halfboxwidth] = obj.calcBoxWidths(subidx); + + % notch depth + notchdepth = obj.notchDepth*halfboxwidth; + + % main nodes + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + q1 = obj.statistics.PL(subidx{:}); + q3 = obj.statistics.PU(subidx{:}); + md = obj.statistics.median(subidx{:}); + nu = obj.statistics.notch_u(subidx{:}); + nl = obj.statistics.notch_l(subidx{:}); + + % set nodes + if obj.notch % if notch requested + Xnodes = [X-halfboxwidth X-halfboxwidth X-halfboxwidth+notchdepth X-halfboxwidth X-halfboxwidth ... + X+halfboxwidth X+halfboxwidth X+halfboxwidth-notchdepth X+halfboxwidth X+halfboxwidth]; + Ynodes = [q1 nl md nu q3 q3 nu md nl q1]; + else % if not + Xnodes = [X-halfboxwidth X-halfboxwidth X+halfboxwidth X+halfboxwidth]; + Ynodes = [q1 q3 q3 q1]; + + end + + % draw box and set props + obj.handles.box(subidx{:}) = patch(Xnodes,Ynodes,'w','Parent',obj.handles.axes); + + if obj.notchLine % if notchLine requested + obj.handles.notchLowerLines(subidx{:}) = line([X-halfboxwidth X+halfboxwidth],[nl nl],... + 'Parent',obj.handles.axes); + obj.handles.notchUpperLines(subidx{:}) = line([X-halfboxwidth X+halfboxwidth],[nu nu],... + 'Parent',obj.handles.axes); + end + + if obj.notch % if notch requested + % median + obj.handles.medianLines(subidx{:}) = line([X-halfboxwidth+notchdepth X+halfboxwidth-notchdepth], [md md]); + else + % median + obj.handles.medianLines(subidx{:}) = line([X-halfboxwidth X+halfboxwidth],[md md]); + end + set(obj.handles.medianLines(subidx{:}),'linestyle','-'); + + if obj.sampleSize % if sample size requested + [~, halfboxwidth] = obj.calcBoxWidths(subidx); + % set x and y offsets + xoffset = 0.15*halfboxwidth; + yoffset = (xoffset./(max(obj.xticks)-min(obj.xticks))).*(max(obj.y(:))-min(obj.y(:))); + gOffset = obj.getOffset(subidx); + % make text + obj.handles.samplesTxt(subidx{:}) = text(obj.xticks(subidx{2})+gOffset+halfboxwidth-xoffset,... + obj.statistics.PU(subidx{:})-yoffset,... + num2str(sum(~isnan(obj.y(subidxAll{:})))),... + 'horizontalalignment','right','verticalalignment','top'); + end + + end + + function drawWhiskers(obj,subidx) + %DRAWWHISKERS draw the whiskers + + try % to delete the handles first + delete(obj.handles.upperWhiskers(subidx{:})); + catch + end + try + delete(obj.handles.lowerWhiskers(subidx{:})); + catch + end + try + delete(obj.handles.upperWhiskerTips(subidx{:})); + catch + end + try + delete(obj.handles.lowerWhiskerTips(subidx{:})); + catch + end + + % vertices + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + [~, halfboxwidth] = calcBoxWidths(obj,subidx); + + % LQ + obj.handles.lowerWhiskers(subidx{:}) = ... + line([X X],[obj.statistics.min(subidx{:}) obj.statistics.PL(subidx{:})],'Parent',obj.handles.axes); + % UQ + obj.handles.upperWhiskers(subidx{:}) = ... + line([X X],[obj.statistics.max(subidx{:}) obj.statistics.PU(subidx{:})],'Parent',obj.handles.axes); + if ~obj.showViolin + % whisker tips + obj.handles.lowerWhiskerTips(subidx{:}) = ... + line([X-0.5*halfboxwidth X+0.5*halfboxwidth],[obj.statistics.min(subidx{:}) obj.statistics.min(subidx{:})],... + 'linestyle','-','Parent',obj.handles.axes); + obj.handles.upperWhiskerTips(subidx{:}) = ... + line([X-0.5*halfboxwidth X+0.5*halfboxwidth],[obj.statistics.max(subidx{:}) obj.statistics.max(subidx{:})],... + 'linestyle','-','Parent',obj.handles.axes); + end + + end + + function drawOutliers(obj,subidx) + %DRAWOUTLIERS draw the outliers + + try % to delete the handles first + delete(obj.handles.outliers(subidx{:})); + catch + end + + if obj.showOutliers + if ~isempty(obj.statistics.outliers{subidx{:}}) % don't bother if no data + % initial plotting vertices + [~, halfboxwidth] = obj.calcBoxWidths(subidx); + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + % add a random x offset based on data distribution + % use full data to calculate offset + subidxAll = subidx; + subidxAll{1} = ':'; + yScatter = obj.y(subidxAll{':'}); + randOffset = obj.xOffset(yScatter); + ix = obj.statistics.outliers_IX(subidxAll{:}); + ix = ix(~isnan(yScatter)); + randOffset = randOffset(ix); + xScatter = X + (0.8.*halfboxwidth.*randOffset); + obj.handles.outliers(subidx{:}) = scatter(xScatter,obj.statistics.outliers{subidx{:}},... + 'Parent',obj.handles.axes); + end + end + + end + + function drawScatter(obj,subidx,gidx,subidxAll) + %DRAWSCATTER draw the scatter overlay + + try % to delete the handles first + delete(obj.handles.scatters(subidx{:})); + catch + end + + if obj.showScatter + + % get non-outliers + IX = ~obj.statistics.outliers_IX(subidxAll{:}); + subidx4 = [{IX} subidx(2:end)]; + + % get data + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + Y = obj.y(subidx4{:}); + + % calculate x offsets + [~,halfboxwidth] = calcBoxWidths(obj,subidx); + if obj.showViolin + halfboxwidth = max(halfboxwidth, obj.calcHalfViolinWidth(subidx)); + end + xScatter = X + (0.8.*halfboxwidth.*obj.xOffset(Y)); + % plot + yScatter = Y(~isnan(Y)); + obj.handles.scatters(subidx{:}) = scatter(xScatter,yScatter,obj.scatterMarker{gidx{:}}); + set(obj.handles.scatters(subidx{:}),'Parent',obj.handles.axes); + end + + end + + function drawMean(obj,subidx) + %DRAWMEAN drawn the means + + try % to delete the handles first + delete(obj.handles.means(subidx{:})); + catch + end + + if obj.showMean + % x position + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + % plot + obj.handles.means(subidx{:}) = plot(X,obj.statistics.mean(subidx{:}),'Parent',obj.handles.axes); + end + + end + + function drawAddPrctiles(obj,subidx) + %DRAWADDPRCTILES draw additional percentiles + + try + delete(obj.handles.addPrctiles(subidx{:})) + catch + end + + if ~isempty(obj.addPrctiles) + subidx2 = subidx; + % x position + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + % plot + h = zeros(length(obj.addPrctiles),1); + for m = 1:length(obj.addPrctiles) + subidx2{1} = m; + Y = obj.statistics.addPrctiles(subidx2{:}); + h(m) = plot(X,Y); + text(X,Y,obj.addPrctilesLabels{m},... + 'horizontalAlignment','left',... + 'verticalAlignment','bottom') + end + subidxAll = subidx; + subidxAll{1} = ':'; + obj.handles.addPrctiles(subidxAll{:}) = h; + end + + end + + function drawGroupGraphics(obj,subidx,gidx) + %DRAWGROUPGRAPHICS set graphics options for each group + + % violin colors + if obj.showViolin + set(obj.handles.violin(subidx{:}),... + 'FaceColor',obj.violinColor{gidx{:}},... + 'EdgeColor',obj.lineColor{gidx{:}}); + end + + % box colors + set(obj.handles.box(subidx{:}),... + 'FaceColor',obj.boxColor{gidx{:}},... + 'EdgeColor',obj.lineColor{gidx{:}}); + + % notch line + if obj.notchLine + set(obj.handles.notchLowerLines(subidx{:}),... + 'linestyle',obj.notchLineStyle{gidx{:}},'color',obj.notchLineColor{gidx{:}}); + set(obj.handles.notchUpperLines(subidx{:}),... + 'linestyle',obj.notchLineStyle{gidx{:}},'color',obj.notchLineColor{gidx{:}}); + end + + % median line + set(obj.handles.medianLines(subidx{:}),'color',obj.medianColor{gidx{:}}); + + % whiskers + set([obj.handles.lowerWhiskers(subidx{:}) obj.handles.upperWhiskers(subidx{:})],... + 'color',obj.lineColor{gidx{:}}); + set([obj.handles.lowerWhiskers(subidx{:}) obj.handles.upperWhiskers(subidx{:})],... + 'linestyle',obj.lineStyle{gidx{:}}); + if ~obj.showViolin + set([obj.handles.lowerWhiskerTips(subidx{:}) obj.handles.upperWhiskerTips(subidx{:})],... + 'color',obj.lineColor{gidx{:}}); + end + + % outliers + if ~isempty(obj.statistics.outliers{subidx{:}}) && obj.showOutliers % don't bother if no data + set(obj.handles.outliers(subidx{:}),... + 'marker',obj.symbolMarker{gidx{:}},'MarkerEdgeColor',obj.symbolColor{gidx{:}}); + end + + % scatter + if obj.showScatter + set(obj.handles.scatters(subidx{:}),'MarkerEdgeColor',obj.scatterColor{gidx{:}}); + end + + % means + if obj.showMean + set(obj.handles.means(subidx{:}),... + 'color',obj.meanColor{gidx{:}},... + 'marker',obj.meanMarker{gidx{:}}); + end + + % additional percentiles + if ~isempty(obj.addPrctiles) + subidx2 = subidx; + for m = 1:length(obj.addPrctiles) + subidx2{1} = m; + set(obj.handles.addPrctiles(subidx2{:}),... + 'color',obj.addPrctilesColors{m},... + 'marker',obj.addPrctilesMarkers{m}); + end + end + + end + + function drawGlobalGraphics(obj) + %DRAWGLOBALGRAPHICS set global graphics options + + % violin + if obj.showViolin + set(obj.handles.violin, ... + 'LineWidth',obj.lineWidth, ... + 'FaceAlpha',obj.violinAlpha); + end + + % box colors + set(obj.handles.box,... + 'FaceAlpha',obj.boxAlpha,... + 'LineWidth',obj.lineWidth); + + % sample size + if obj.sampleSize + set(obj.handles.samplesTxt,'fontsize',obj.sampleFontSize); + end + + % notch line + if obj.notchLine + set(obj.handles.notchLowerLines,'linewidth',obj.lineWidth); + set(obj.handles.notchUpperLines,'linewidth',obj.lineWidth); + end + + % median line + set(obj.handles.medianLines,'linewidth',obj.lineWidth); + + % whiskers + set([obj.handles.lowerWhiskers obj.handles.upperWhiskers],... + 'linewidth',obj.lineWidth); + if ~obj.showViolin + set([obj.handles.lowerWhiskerTips obj.handles.upperWhiskerTips],... + 'linewidth',obj.lineWidth); + end + + % outliers + if obj.showOutliers && isfield(obj.handles,'outliers') + set(findobj(obj.handles.outliers,'Type','Scatter'),... + 'SizeData',obj.outlierSize); + end + + % scatter + if obj.showScatter && isfield(obj.handles,'scatters') + set(obj.handles.scatters,'SizeData',obj.scatterSize); + if obj.scatterAlpha<1 + try % older versions do not support MarkerEdgeAlpha + set(obj.handles.scatters,'MarkerEdgeAlpha',obj.scatterAlpha); + catch + warning('This version of Matlab does not support scatter marker transparency.') + end + end + end + + % means + if obj.showMean && isfield(obj.handles,'means') + set(obj.handles.means,'markersize',obj.meanSize); + end + + % set group label font size + if isfield(obj.handles,'groupsTxt') + set(obj.handles.groupsTxt,'FontSize',obj.groupLabelFontSize); + end + + % set additional percentile font size + if ~isempty(obj.addPrctiles) && isfield(obj.handles,'addPrctilesTxt') + set(obj.handles.addPrctilesTxt,'FontSize',obj.addPrctilesTxtSize); + end + + end + + function drawXsepatator(obj) + %DRAWXSEPARATOR draw the x separator lines + + try % to delete the handles first + delete(obj.handles.xseps); + catch + end + + if obj.xSeparator + xlines = obj.xticks(1:end-1)+0.5.*diff(obj.xticks); % line positions + obj.handles.xseps = zeros(size(xlines)); % handles + for n = 1:length(xlines) % draw lines + obj.handles.xseps(n) = line([xlines(n) xlines(n)],get(obj.handles.axes,'ylim'),'color',.5+zeros(1,3)); + end + end + end + + function drawStyle(obj) + %DRAWSTYLE draw the style options + + try % to delete the handles first + delete(obj.handles.groupsTxt); + catch + end + + % get outermost box widths (correct xlim for this) + subidxFirst = cell(1,length(obj.outDims)); + [subidxFirst{:}] = ind2sub(obj.outDims, 1); + [~,halfboxwidthFirst] = calcBoxWidths(obj,subidxFirst); + subidxLast = cell(1,length(obj.outDims)); + [subidxLast{:}] = ind2sub(obj.outDims, prod(obj.outDims)); + [~,halfboxwidthLast] = calcBoxWidths(obj,subidxLast); + + % set default x axis + set(obj.handles.axes,'xtick',obj.xticks,... + 'xlim',[min(obj.xticks)-0.5*obj.diffx-halfboxwidthFirst max(obj.xticks)+0.5*obj.diffx+halfboxwidthLast],... + 'xticklabel',obj.xlabels); + + switch lower(obj.style) + case 'normal' + % do nothing + case 'hierarchy' + + % check grouplabels options + if ~isempty(obj.groupLabels) + assert(isvector(obj.groupLabels) && iscell(obj.groupLabels),... + 'iosr:boxPlot:groupLabelsType', ... + 'The GROUPLABELS option should be a cell vector'); + if ~isempty(obj.outDims(3:end)) + assert(isequal(obj.outDims(3:end),cellfun(@length,obj.groupLabels)),... + 'iosr:boxPlot:groupLabelsSize', ... + ['The GROUPLABELS option should be a cell vector; ' ... + 'the Nth element should contain a vector of length SIZE(Y,N+2)']) + else + assert(cellfun(@length,obj.groupLabels)==1,... + 'iosr:boxPlot:groupLabelsSize', ... + 'The GROUPLABELS option should have length 1 if no grouping dimensions are specified.') + end + end + + % number of label rows + labelrows = length(obj.outDims)-1; + + ylim = get(obj.handles.axes,'ylim'); % need y limitis + + if isnumeric(obj.groupLabelHeight) + labelheight = obj.groupLabelHeight; + else + % determine label height + labelheight = obj.calcLabelHeight(); % y range in units calculated based on normalised height + end + + % determine y centre points of labels based on how many labels + % and their height + ymids = ylim(1) - (labelrows:-1:1).*labelheight + 0.5.*labelheight; + + % clear axis tick labels + set(obj.handles.axes,'xticklabels',[]); + + % put labels on plot + totalticks = prod(obj.outDims(2:end)); % total number of ticks across + allticklocs = sort(obj.groupXticks(:)); % their locations + obj.handles.groupsTxt = []; + for c = labelrows:-1:1 % work down hierarchy + Y = ymids(c); % y location + nskip = totalticks/prod(obj.outDims(2:c+1)); % skip through tick locations based on hierarchy + first = 1:nskip:totalticks; % first tick in group + last = nskip:nskip:totalticks; % last tick in group + labellocs = allticklocs(first) + 0.5.*(allticklocs(last)-allticklocs(first)); % centre point for label location + % work through each label location + for n = 1:length(labellocs) + if c==1 % special case: x axis ticks + gLabel = obj.xlabels{n}; + else % every other group + if isempty(obj.groupLabels) % auto increment label + gLabel = num2str(mod(n-1,obj.outDims(c+1))+1); + else % get from input + gLabel = obj.groupLabels{c-1}(mod(n-1,obj.outDims(c+1))+1); % cyclic index into labels + if isnumeric(gLabel) % convert numbers to strings + gLabel = num2str(gLabel); + end + end + end + % place actual label + t = text(labellocs(n),Y,gLabel,'HorizontalAlignment','center','VerticalAlignment','middle'); + % store info about placement + setappdata(t,'rows',labelrows); + setappdata(t,'row',c); + % add to handles + obj.handles.groupsTxt = [obj.handles.groupsTxt t]; + end + + end + otherwise + error('iosr:boxPlot:unknownStyle','Unkown ''style'' option.') + end + + end + + function drawLegend(obj) + %DRAWLEGEND draw the legend + + try % to delete the handles first + delete(obj.handles.legend); + catch + end + + if obj.showLegend + % dimensions of group data + gDims = cellfun(@length,obj.groupLabels); + if isempty(gDims) + gDims = 1; + end + subidx = cell(1,length(gDims)); + % going to change order of handles + orderidx = cell(1,length(gDims)+1); + order = zeros(prod(gDims),1); + % preallocate legend labels + lgndstr = cell(prod(gDims),1); + for n = 1:prod(gDims) + % use linear index to get group data + [subidx{:}] = ind2sub([gDims 1], n); + % order looks at trailing dimensions first + [orderidx{:}] = ind2sub(fliplr([gDims 1]), n); + orderidx = fliplr(orderidx); + order(n) = sub2ind([gDims 1],orderidx{:}); + % create labels + start = true; % create start of string label + for m = length(subidx):-1:1 % work from end through dimensions + str = obj.ensureString(obj.groupLabels{m}(subidx{m})); + if start % initialise label + lgndstr{n} = str; + start = false; + else % prepend string label + lgndstr{n} = [str ', ' lgndstr{n}]; + end + end + end + % choose target for the legend + if ~obj.arrayElementsEqual(obj.boxColor) + legendTarget = obj.handles.box; + target = 'box'; + elseif ~obj.arrayElementsEqual(obj.medianColor) + legendTarget = obj.handles.medianLines; + target = 'medianLines'; + elseif obj.showViolin && ~obj.arrayElementsEqual(obj.violinColor) + legendTarget = obj.handles.violin; + target = 'violin'; + else + error('iosr:boxPlot:legend','The legend uses the box, median line colors, or violins to create legend entries. However, these items appear to be identical, which would make the legend impossible to interpret. Change the ''boxColor'', ''medianColor'', or ''violinColor'' option.'); + end + % create legend in specified order + if ~isempty(legendTarget) + [obj.handles.legend, icons] = legend(legendTarget(1,1,order),lgndstr(order)); + set(obj.handles.legend,'location','best'); + % add alpha to legend entries + PatchInLegend = findobj([obj.handles.legend; icons(:)], 'type', 'patch'); + if ~isempty(PatchInLegend) + switch lower(target) + case 'box' + set(PatchInLegend, 'facealpha', obj.boxAlpha); + case 'violin' + set(PatchInLegend, 'facealpha', obj.violinAlpha); + end + end + end + end + end + + function createTheme(obj) + %CREATETHEME create the color/line theme + + switch lower(obj.theme) % choose scheme + case 'colorall' + boxalpha = 0.4; + boxcolor = obj.themeColors; + linecolor = 'k'; + linestyle = '-'; + meancolor = 'k'; + mediancolor = 'k'; + notchlinecolor = obj.themeColors; + notchlinestyle = ':'; + scattercolor = obj.themeColors; + symbolcolor = obj.themeColors; + case {'colorlines', 'graylines'} + if strcmpi(obj.theme,'graylines') + warning('iosr:boxPlot:graylines', 'The ''graylines'' theme is deprecated. Use the ''colorlines'' theme instead, and specify ''themeColors'' as @gray.') + end + boxalpha = obj.boxAlpha; + boxcolor = 'none'; + linecolor = 'k'; + linestyle = '-'; + meancolor = 'k'; + mediancolor = obj.themeColors; + notchlinecolor = obj.themeColors; + notchlinestyle = ':'; + scattercolor = obj.themeColors; + symbolcolor = obj.themeColors; + case {'colorboxes', 'grayboxes'} + if strcmpi(obj.theme,'grayboxes') + warning('iosr:boxPlot:grayboxes', 'The ''grayboxes'' theme is deprecated. Use the ''colorboxes'' theme instead, and specify ''themeColors'' as @gray.') + end + boxalpha = obj.boxAlpha; + boxcolor = obj.themeColors; + linecolor = 'k'; + linestyle = '-'; + meancolor = 'k'; + mediancolor = 'k'; + notchlinecolor = 'k'; + notchlinestyle = ':'; + scattercolor = [.5 .5 .5]; + symbolcolor = 'k'; + otherwise + if ~strcmpi(obj.theme,'default') + warning(['Unknown theme ''' obj.theme ''' specified. Using default']) + end + boxalpha = 1; + boxcolor = 'none'; + linecolor = 'k'; + linestyle = '-'; + meancolor = obj.themeColors; + mediancolor = obj.themeColors; + notchlinecolor = 'k'; + notchlinestyle = ':'; + scattercolor = [.5 .5 .5]; + symbolcolor = obj.themeColors; + end + % turn off legend while changing parameters + legendState = obj.showLegend; + obj.showLegend = false; + % set parameters + obj.boxAlpha = boxalpha; + obj.boxColor = boxcolor; + obj.medianColor = mediancolor; + obj.lineColor = linecolor; + obj.lineStyle = linestyle; + obj.meanColor = meancolor; + obj.notchLineColor = notchlinecolor; + obj.notchLineStyle = notchlinestyle; + obj.scatterColor = scattercolor; + obj.symbolColor = symbolcolor; + % turn legend back on if it was on + obj.showLegend = legendState; + end + + function calculateStats(obj) + %CALCULATESTATS calculate the statistic for the box plot + + calculateStats@iosr.statistics.statsPlot(obj); + + % calculate stats + obj.statistics.percentile = obj.percentile; % percentile + outsize = size(obj.statistics.median); + obj.statistics.addPrctiles = zeros([length(obj.addPrctiles) outsize(2:end)]); + obj.statistics.PL = zeros(outsize); % lower percentile + obj.statistics.PU = zeros(outsize); % upper percentile + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(obj.outDims) + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = subidx; + subidxAll{1} = ':'; + if ~isempty(obj.addPrctiles) + obj.statistics.addPrctiles(subidxAll{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),obj.addPrctiles(:)./100,[],obj.method,obj.weights(subidxAll{:})); + end + obj.statistics.PL(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),min(obj.percentile)/100,[],obj.method,obj.weights(subidxAll{:})); + obj.statistics.PU(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),max(obj.percentile)/100,[],obj.method,obj.weights(subidxAll{:})); + end + + % check for notches extending beyond box + if (any(obj.statistics.notch_u(:)>obj.statistics.Q3(:)) || any(obj.statistics.notch_l(:)<obj.statistics.Q1(:))) && (obj.notch || obj.notchLine) + warning('Notch extends beyond quartile. Try setting ''notch'' or ''notchLine'' to false') + end + + end + + function setXprops(obj) + %SETXPROPS set x axis properties + + if isnumeric(obj.x) % x is numeric + obj.xlabels = strtrim(cellstr(num2str(obj.x(:)))); + switch lower(obj.xSpacing) % choose spacing + case 'x' + obj.xticks = obj.x; + obj.diffx = min(diff(obj.x)); + if isempty(obj.diffx) + obj.diffx = 1; + end + case 'equal' + obj.xticks = 1:length(obj.x); + obj.diffx = 1; + otherwise + error('iosr:boxPlot:xSpacing','Unknown xSpacing option specified.') + end + else % x is not numeric + obj.xlabels = obj.x; + obj.xticks = 1:length(obj.x); + obj.diffx = 1; + end + obj.groupRange = obj.groupWidth*obj.diffx; + end + + function out = groupOption(obj,option,name) + %GROUPOPTION convert parameter to format for plotting + + gDims = obj.groupDims; + if length(gDims)==1 + gDims = [gDims 1]; + end + + % checks + if ischar(option) + option = cellstr(option); % ensure string is cell array + elseif isnumeric(option) + option = {option}; + end + if isvector(option) + option = option(:); + end + + % pre-allocate output + out = cell(gDims); + + % create output + if length(option)==1 % repeat if only one specified + for n = 1:prod(gDims) + out(n) = option; + end + elseif isequal(gDims,size(option)) % put into cell array + for n = 1:prod(gDims) + assert(ischar(option{n}) || size(option{n},2)==3, 'iosr:boxPlot:groupOptionFormat', ['Option ''' name ''' is not in the correct format.']) + out(n) = option(n); + end + else + error('iosr:boxPlot:groupOptionSize','Option ''%s'' is not the correct size.',name) + end + + end + + function out = checkColor(obj,color,usage) + %checkColor convert 'auto' color option to RGB + + gDims = obj.groupDims; + out = color; % pass input to output + + if ischar(color) + if strcmpi(color,'auto') + color = @lines; + end + end + + if isa(color,'function_handle') + obj.checkColorHandle(color); + out = cell([gDims 1]); + if any(strcmpi(char(color),{'hot','gray','bone','copper','pink'})) + N = 512; + cmapTest = color(N); + YL = 0.2989.*cmapTest(:,1) + 0.5870*cmapTest(:,2) + 0.1140.*cmapTest(:,3); % luminance + switch lower(usage) + case 'fill' + % ensure minimum luminance of 0.33 + firstLumaIX = find(YL>0.33,1,'first'); + if numel(out)<=N + cmap = cmapTest(round(linspace(firstLumaIX,N,numel(out))),:); % sample color map + else + pad = ceil((firstLumaIX/N)*numel(out)); % pad for the black region + cmap = color(numel(out)+pad); % colormap + cmap = cmap(pad+1:end,:); % remove padded region + end + case 'line' + % ensure maximum luminance of 0.66 + lastLumaIX = find(YL<0.66,1,'last'); + if numel(out)<=N + cmap = cmapTest(round(linspace(1,lastLumaIX,numel(out))),:); % sample color map + else + pad = ceil(((N-lastLumaIX)/N)*numel(out)); % pad for the black region + cmap = color(numel(out)+pad); % colormap + cmap = cmap(1:end-pad,:); % remove padded region + end + end + else + cmap = color(numel(out)); % colormap + end + for n = 1:numel(out) + out{n} = cmap(n,:); + end + end + + end + + function [boxwidth, halfboxwidth] = calcBoxWidths(obj,subidx) + %CALCBOXWIDTHS calculate the box width + + % size of boxes + if ischar(obj.boxWidth) + boxwidth = 0.75*(obj.groupRange/prod(obj.groupDims)); + else + boxwidth = obj.boxWidth; + end + + if obj.scaleWidth + % scale box width according to sample size + maxN = max(obj.statistics.N(:)); + halfboxwidth = 0.5 * (sqrt(obj.statistics.N(subidx{:})/maxN)*boxwidth); + else + % normal box width + halfboxwidth = boxwidth/2; + end + + end + + function halfviolinwidth = calcHalfViolinWidth(obj,subidx) + %HALFVIOLINWIDTH calculate the violin width + + % size of boxes + if ischar(obj.violinWidth) + halfviolinwidth = 0.75*(obj.groupRange/prod(obj.groupDims)); + else + halfviolinwidth = obj.violinWidth; + end + + if obj.scaleWidth + % scale box width according to sample size + maxN = max(obj.statistics.N(:)); + halfviolinwidth = 0.5 * (sqrt(obj.statistics.N(subidx{:})/maxN)*halfviolinwidth); + else + halfviolinwidth = halfviolinwidth / 2; + end + + end + + function labelheight = calcLabelHeight(obj) + %CALCLABELHEIGHT calculate the label height for the axes + + ylim = get(obj.handles.axes,'ylim'); + plotheight = get(obj.handles.axes,'position'); % plot position + plotheight = plotheight(4); % plot height in normalised units + plotrange = abs(diff(ylim)); % y range + labelheight = plotheight*plotrange*0.05; % y range in units calculated based on normalised height + + end + + function offset = getOffset(obj,subidx) + %GET_OFFSET calculate offset for hierarchical data + + dims = obj.outDims(3:end); + subidx = subidx(3:end); + if isempty(dims) || prod(dims)==1 + offset = 0; + else + boxspacing = obj.groupRange/prod(obj.groupDims); + offsetn = (0:prod(dims)-1)-((prod(dims)-1)./2); + n = sub2ind([dims(end:-1:1) 1],subidx{end:-1:1}); + offset = offsetn(n).*boxspacing; + end + + end + + function val = checkAddPrctileProp(obj,init,default) + %CHECKADDPRCTILEPROP check and set default values of additional percentile properties + + val = init(:); + currlength = length(val); + if currlength<length(obj.addPrctiles) + val = [val; cell(length(obj.addPrctiles)-currlength,1)]; + for m = currlength+1:length(obj.addPrctiles) + val(m) = default; + end + end + end + + function eventHandler(obj,hProp,eventData) + %EVENTHANDLER handle axes property change events + + propName = hProp.Name; + propValue = eventData.AffectedObject.(propName); + + % update separator lines + if strcmpi(propName,'YLim') + % correct x separator limits + if isfield(obj.handles,'xseps') + ydata = propValue; + if any(isinf(propValue)) + % inf uses actual data to determine limits + ylim = [NaN NaN]; + children = get(obj.handles.axes,'children'); + for n = 1:length(children) + try + d = get(children(n),'YData'); + ylim(1) = min([ylim(1); d]); + ylim(2) = max([ylim(2); d]); + catch + % ignore objects that don't have YData + end + end + % replace occurences of inf + ydata(isinf(propValue)) = ylim(isinf(propValue)); + end + set(obj.handles.xseps,'YData',ydata); + end + % move group labels up or down + if isfield(obj.handles,'groupsTxt') + labelheight = obj.calcLabelHeight(); + for n = 1:length(obj.handles.groupsTxt) + % current position + pos = get(obj.handles.groupsTxt(n),'Position'); + % new position + rows = getappdata(obj.handles.groupsTxt(n),'rows'); + row = getappdata(obj.handles.groupsTxt(n),'row'); + pos(2) = propValue(1) - (rows-row+.5)*labelheight; + % set it + set(obj.handles.groupsTxt(n),'Position',pos); + end + end + end + + end + + end + + methods (Static, Access = private) + + function offset = xOffset(y) + %XOFFSET create an x offset based on data distribution + + y = y(~isnan(y)); + [d, xd] = iosr.statistics.kernelDensity(y); + d = d./max(d); + + try + maxDisplacement = interp1(xd, d, y); + catch + maxDisplacement = zeros(size(y)); + end + randOffset = rand(size(y));%randperm(numel(y))-1; + randOffset = (2*randOffset) - 1; + % randOffset = (2*randOffset./max(randOffset)) - 1; + offset = randOffset(:) .* maxDisplacement; + + end + + function str = ensureString(val) + %ENSURESTRING ensure input value is a string or convert to a string + + if isnumeric(val) + str = num2str(val); + elseif ischar(val) + str = val; + elseif iscellstr(val) + str = char(val); + else + error('iosr:boxPlot:ensureString','Unable to convert data type to string.') + end + + end + + function equal = arrayElementsEqual(v) + %ARRAYELEMENTSEQUAL check if elements in array are the same + + x = v(:); + if iscell(x) && ~iscellstr(x) + x = cell2mat(x); % convert numeric cell arrays to numeric arrays + end + equal = numel(unique(x))==1; + + end + + function checkColorHandle(fHandle) + %CHECKCOLORHANDLE check whether function handle reurns valid color output + + for N = [1 4 8 16] + assert(isequal(size(fHandle(N)),[N 3]), 'iosr:boxPlot:colorFhandle', ['The color function ''' char(fHandle) ''' does not appear to return a color array of the correct size.']) + cOutput = fHandle(N); + assert(all(cOutput(:)>=0) && all(cOutput(:)<=1), 'iosr:boxPlot:colorFhandleRange', ['The color ''' char(fHandle) ''' function does not appear to return RGB values in the interval [0,1].']) + end + end + + function option = replaceAuto(option, default, errorMsg) + %REPLACEAUTO check for and replace auto parameters + if ischar(option) + if strcmpi(option, 'auto') + option = default; + else + error('iosr:boxPlot:invalidOption',errorMsg) + end + end + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalBoxPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalBoxPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..7299dbe783299ff7571ab1c0e19308b777983fb1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalBoxPlot.m @@ -0,0 +1,365 @@ +classdef (CaseInsensitiveProperties = true) functionalBoxPlot < ... + iosr.statistics.functionalPlot +%FUNCTIONALBOXPLOT Draw a functional boxplot +% +% Use this class to plot a functional boxplot [1]. A functional boxplot +% considers each function as a single observation. The order statistics +% are calculated from the band depth (BD) or modified band depth (MBD) of +% each function; the appearance of the functional boxplot is derived +% analogously to the traditional boxplot. The plot shows the median +% function, the 50% central region, and the functional limits +% ([Q1-1.5*IQR, Q3+1.5*IQR], where Q1 and Q3 are the 25th and 75th +% percentiles respectively, and IQR is the interquartile range). Outliers +% (functions exceeding this limit) may also be plotted. +% +% FUNCTIONALBOXPLOT operates on the array Y, which is an N-by-M-by-P +% array, where N functions are stored across the rows of Y, there are M +% X-values, and there are P functional plots. +% +% IOSR.STATISTICS.FUNCTIONALBOXPLOT properties: +% method - Specifies the method used to calculate +% the band depth. +% outlierLineColor - Specifies the color of the outlier lines. +% outlierLineStyle - Specifies the width of the outlier marker +% line. See 'mainLineWidth' for details of +% how to specify widths. The default is 1. +% +% Additional properties are inherited from +% IOSR.STATISTICS.FUNCTIONALPLOT. +% +% These properties can be referenced using dot notation - e.g. H.METHOD +% where H is an instance of the FUNCTIONALBOXPLOT object - or using +% the SET and GET methods - e.g. GET(H,'METHOD'). Both methods are +% case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% Read-only properties: +% x - The x data. +% y - The y data. +% statistics - Structure containing the statistics used +% for the box plot. With the exception of +% 'outliers', each field contains a 1-by-M-by-P +% numeric array of values (identical to that +% returned by IOSR.STATISTICS.QUANTILE). The +% fields are: +% 'inner_l' : the 25th percentile +% 'inner_u' : the 75th percentile +% 'main' : the values of the +% central line +% 'outer_l' : the lower limits +% 'outer_u' : the upper limits +% 'outliers' : a 1-by-P cell array of +% outlier functions +% +% IOSR.STATISTICS.FUNCTIONALBOXPLOT methods: +% FUNCTIONALBOXPLOT - Create the plot. +% +% References +% +% [1] Sun, Y.; Genton, M. G. (2011). "Functional boxplots". Journal of +% Computational and Graphical Statistics. 20: 316?334. +% doi:10.1198/jcgs.2011.09224 +% +% See also IOSR.STATISTICS.BOXPLOT, IOSR.STATISTICS.QUANTILE, +% IOSR.STATISTICS.FUNCTIONALPLOT, IOSR.STATISTICS.FUNCTIONALSPREADPLOT. + +% Adapted from code originally written by: +% - Ying Sun: sunwards@stat.tamu.edu +% - Marc G. Genton: genton@stat.tamu.edu + + properties (AbortSet) + method = 'mbd' % The method used to calculate the quantiles. + outlierLineColor = 'auto' % Color of the outlier lines + outlierLineStyle = '-' % Width of the outlier lines. + end + + properties (Access = private) + depths + end + + methods + + % constructor + function obj = functionalBoxPlot(varargin) + % FUNCTIONALBOXPLOT Draw a functional boxplot. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(Y) produces a functional + % boxplot of the data in Y. Y should be an N-by-M or N-by-M-by-P + % array, where N functions are stored in the rows of Y, there are + % M X-values, and there are P functional plots. The plot shows + % the median function as the main line, the interquartile range + % as the shaded region, lines showing the limits of the data, and + % lines showing any outlier functions. + % + % Tabular data can be arranged into the appropriate format using + % the IOSR.STATISTICS.TAB2BOX function. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(X,Y) specifies the x-axis + % values for the plot. X should be an M-length vector. The + % default is 1:M. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(...,'PARAMETER',VALUE) + % allows the plotting options to be specified when the plot is + % constructed. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(AX,...) creates the plot + % in the axes specified by AX. + % + % Example + % + % % generate random data + % y = cat(3, randn(100,21), 0.25+randn(100,21)); + % x = 0:20; + % + % % Draw a functional box plot for the first function + % figure + % iosr.statistics.functionalBoxPlot(x, y(:,:,1)); + % title('Functional boxplot.') + % axis tight + % box on + + start = obj.getXY(varargin{:}); + + % check input is valid size + assert(ndims(obj.y) <= 3 && ndims(obj.y) >= 2, ... + 'iosr:functionalBoxPlot:invalidY', ... + 'Y must be a two- or three-dimensional array.'); + + % set the properties of the plot + obj.whiskers = true; + obj.setProperties(start,nargin,varargin); + + % remove NaN columns + obj.removeNaN(); + + % calculate the statistics used in the plot + obj.calculateStats(); + + %% draw + + % set handles + obj.parseAxesHandle(varargin{:}); + + % draw the box plot + obj.draw(); + + end + + %% Accessors / Mutators + + function set.method(obj, val) + obj.method = val; + obj.calculateStats(); + obj.draw(); + end + + function val = get.outlierLineColor(obj) + val = obj.parseColor(obj.outlierLineColor); + end + + function val = get.outlierLineStyle(obj) + val = obj.parseProps(obj.outlierLineStyle, false); + end + + end + + methods (Access = protected) + + % calculate the statistics used in the plot + function calculateStats(obj) + + obj.depths = obj.bandDepth(); + nCurves = size(obj.y, 1); + + % Calculate specific stats + outsize = [1 obj.ydims(2:end)]; + outDimsTemp = [1 1 obj.outDims(3:end)]; + obj.statistics.main = zeros(outsize); + obj.statistics.inner_u = zeros(outsize); + obj.statistics.inner_l = zeros(outsize); + obj.statistics.outer_u = zeros(outsize); + obj.statistics.outer_l = zeros(outsize); + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(outDimsTemp) + [subidx{:}] = ind2sub(outDimsTemp, n); + subidx{2} = ':'; + subidxAll = subidx; + subidxAll{1} = ':'; + + data = obj.y(subidxAll{:}); + + % main statistics + [~,index] = sort(obj.depths,'descend'); + m = ceil(nCurves*0.5); + center = data(index(1:m),:); + inf = min(center); + sup = max(center); + dist = 1.5*(sup-inf); + upper = sup+dist; + lower = inf-dist; + + % outliers + outly = sum(or(data'<=lower'*ones(1,nCurves), data'>=upper'*ones(1,nCurves)))'; + outpoint = find(outly); + outliers = data(outpoint,:); + good = data; + good(outpoint,:)=[]; + maxcurve = max(good); + mincurve = min(good); + + % parent class uses these fields for plotting + obj.statistics.inner_u(subidx{:}) = sup; + obj.statistics.inner_l(subidx{:}) = inf; + obj.statistics.outer_u(subidx{:}) = maxcurve; + obj.statistics.outer_l(subidx{:}) = mincurve; + obj.statistics.main(subidx{:}) = data(index(1),:); + obj.statistics.outliers{n} = outliers; + + end + + end + + % Draw the plot + function draw(obj) + + if isfield(obj.handles,'axes') + + axes(obj.handles.axes); + cla; + hold on; + + % parent class does most of the plotting + draw@iosr.statistics.functionalPlot(obj); + + % plot outlier functions + if length(obj.outDims) > 2 + nlines = obj.outDims(3); + else + nlines = 1; + end + if obj.showOutliers + for n = nlines:-1:1 + % draw inner patch + if ~isempty(obj.statistics.outliers{n}) + obj.handles.outliers{n} = line(obj.x, obj.statistics.outliers{n}, ... + 'linestyle', obj.outlierLineStyle{n}, ... + 'linewidth', obj.outlierLineWidth{n}, ... + 'color', obj.outlierLineColor{n} ... + ); + end + end + else + try + delete(obj.handles.outliers) + catch + end + end + + end + + end + + end + + methods (Access = private) + + % calculate band depth + function depth = bandDepth(obj) + + switch lower(obj.method) + case 'bd2' + depth = obj.BD2(); + case 'bd3' + depth = obj.BD3(); + case 'mbd' + depth = obj.MBD(); + otherwise + error('iosr:functionalBoxPlot:unknownMethod',['Unknown mode ''' obj.method '''']) + end + + end + + + function contg = MBD(obj) + % calculates the generalized band depth of a set of data + n = size(obj.y,1); % size of the data matrix + cont = zeros(n,1,obj.outdims(3)); + for p = 1:obj.outdims(3) + for i=1:(n-1) + for j=(i+1):(n) % consider all possible pairs of functions + cont(:,:,p) = cont(:,:,p)+obj.a(obj.y(:,:,p), [i j]); + end + end + end + contg=cont/obj.combinat(n,2); + end + + function contg = BD3(obj) + % calculate the band depth with J=3. + n=size(obj.y,1); + cont=zeros(n,1,obj.outdims(3)); + % Select three observations from the sample in all the possible ways. + for p = 1:obj.outdims(3) + for i=1:(n-2) + for j=(i+1):(n-1) + for k=(j+1):n + cont(:,:,p) = cont(:,:,p)+obj.estaEntre(obj.y(:,:,p), [i j k])'; % In this subfunction we check which observations from the sample is inside the band delimeted by observations i,j and k. + + end + end + end + end + contg=cont/obj.combinat(n,3); + end + + function contg = BD2(obj) + % calculate the band depth of every observation in the matrix + n=size(obj.y,1); + cont=zeros(n, 1, obj.outdims(3)); + for p = 1:obj.outdims(3) + for i=1:((n+2)/3) + for j=(i+1):(n) % choose pairs of indexes in all the possible ways. + cont(:,:,p) = cont(:,:,p)+obj.estaEntre(obj.y(:,:,p), [i j])'; + end + end + end + contg =cont/obj.combinat(n,2); + end + + end + + methods (Static, Access = private) + + function resultado = a(data, v) + n = size(data,1); + p = size(data,2); + Z = data; + inf=(min(Z(v,:)))'; + sup=(max(Z(v,:)))'; + resul=sum((and(Z'<=sup*ones(1,n),Z'>=inf*ones(1,n)))); + % Proportion of coordinates of each observation from the sample + % that is inside the band delimited by pairs v of functions from the sample. + resultado=(resul/p)'; + end + + function resultados = estaEntre(data, v) + [n,p]=size(data); + Z=data; + inf=min(Z(v,:))'; + sup=max(Z(v,:))'; + resultados=sum((and(Z'<=sup*ones(1,n),Z'>=inf*ones(1,n))))==p; + end + + function combinat = combinat(n,p) + if n<p + combinat=0; + else + combinat = nchoosek(n,p); + end + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..3b1a87d83332c7aa1a457844a1c71efd48920afd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalPlot.m @@ -0,0 +1,387 @@ +classdef (Abstract, CaseInsensitiveProperties = true) functionalPlot < ... + iosr.statistics.statsPlot +%FUNCTIONALPLOT Abstract superclass for functional plots +% +% As an abstract class, this class cannot be instantiated. It provides no +% public methods. The class is a super class for: +% - iosr.statistics.functionalBoxPlot +% - iosr.statistics.functionalSpreadPlot +% +% The class does, however, provide various properties to subclasses. +% +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT properties: +% mainLineColor - Specifies the color of the central line. +% See 'addPrctilesLineColor' for details of +% how to specify colors. The default is +% 'auto'. +% mainLineStyle - Specifies the style of the central line. +% The property may be specified as a char +% array (e.g. '-'), or as a length-P cell +% vector of strings (if passing line styles +% for each functional plot). The default is +% '-'. +% mainLineWidth - Specifies the width of the central line. +% The property may be specified as a +% length-P numeric vector, or as a cell +% vector (if passing line styles for each +% functional plot). The default is 1. +% outerLineColor - Specifies the color of the outer lines. +% See 'mainLineStyle' for details of how to +% specify colors. The default is 'auto'. +% outerLineStyle - Specifies the style of the outer lines. +% See 'mainLineStyle' for details of how to +% specify styles. The default is '-'. +% outerLineWidth - Specifies the width of the outer line. +% See 'mainLineWidth' for details of how to +% specify widths. The default is 1. +% outlierLineWidth - Specifies the width of the outlier marker +% line. See 'mainLineWidth' for details of +% how to specify widths. The default is 1. +% showOutliers - Specifies whether to show outliers. The +% property must be a logical value. The +% default is false. +% spreadAlpha - Set the alpha of the shaded region(s). +% The default is 0.5. +% spreadBorderLineColor - Set the color of the shaded regions' +% / region's border. See +% 'addPrctilesLineColor' for details of how +% to specify colors. The default is 'none'. +% spreadBorderLineWidth - Set the width of the shaded regions' +% / region's border. The default is 1. +% spreadColor - Set the color of the shaded region(s). +% See 'addPrctilesLineColor' for details of +% how to specify colors. The default is +% 'auto'. +% whiskers - Specify whether the box is connected to +% the outer line via a whisker. The line is +% drawn with the same style as the outer +% line. The default is false. +% +% These properties can be referenced using dot notation - e.g. H.BOXCOLOR +% where H is an instance of the FUNCTIONALSPREADPLOT object - or using +% the SET and GET methods - e.g. GET(H,'BOXCOLOR'). Both methods are +% case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% See also IOSR.STATISTICS.BOXPLOT, IOSR.STATISTICS.QUANTILE, +% IOSR.STATISTICS.FUNCTIONALBOXPLOT, +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT, IOSR.STATISTICS.STATSPLOT. + + properties (AbortSet) + mainLineColor = 'auto' % The color of the central line. + mainLineStyle = '-' % The style of the central line. + mainLineWidth = 2 % The width of the central line. + outerLineColor = 'auto' % The color of the outer lines. + outerLineStyle = '-' % The style of the outer lines. + outerLineWidth = 0.5 % The width of the outer lines. + outlierLineWidth = 1 % Width of the outlier marker edges. + showOutliers = true % Turn outliers on and off. + spreadAlpha = 0.5 % The alpha of the shaded regions. + spreadColor = 'auto' % The color of the shaded regions. + spreadBorderLineWidth = 1 % The width of the shaded region borders. + spreadBorderLineColor = 'none' % The color of the shaded region borders. + whiskers = false % Specify whether a line connects the box to the outer lines. + end + + methods + + function set.showOutliers(obj, val) + assert(numel(val)==1 && islogical(val), 'iosr:functionalPlot:invalidShowOutliers', ... + '''SHOWOUTLIERS'' must be true or false.') + obj.showOutliers = val; + obj.draw(); + end + + % main lines + + function val = get.mainLineColor(obj) + val = obj.parseColor(obj.mainLineColor); + end + + function set.mainLineColor(obj,val) + obj.mainLineColor = val; + obj.draw(); + end + + function val = get.mainLineStyle(obj) + val = obj.parseProps(obj.mainLineStyle, false); + end + + function set.mainLineStyle(obj,val) + obj.mainLineStyle = val; + obj.draw(); + end + + function val = get.mainLineWidth(obj) + val = obj.parseProps(obj.mainLineWidth, false); + end + + function set.mainLineWidth(obj,val) + obj.mainLineWidth = val; + obj.draw(); + end + + % outer lines + + function val = get.outerLineColor(obj) + val = obj.parseColor(obj.outerLineColor); + end + + function set.outerLineColor(obj,val) + obj.outerLineColor = val; + obj.draw(); + end + + function val = get.outerLineStyle(obj) + val = obj.parseProps(obj.outerLineStyle, false); + end + + function set.outerLineStyle(obj,val) + obj.outerLineStyle = val; + obj.draw(); + end + + function val = get.outerLineWidth(obj) + val = obj.parseProps(obj.outerLineWidth, false); + end + + function set.outerLineWidth(obj,val) + obj.outerLineWidth = val; + obj.draw(); + end + + % outlier settings + + function val = get.outlierLineWidth(obj) + val = obj.parseProps(obj.outlierLineWidth, false); + end + + function set.outlierLineWidth(obj,val) + obj.outlierLineWidth = val; + obj.draw(); + end + + % set spread alpha + + function set.spreadAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:functionalPlot:invalidSpreadAlpha', ... + '''SPREADALPHA'' must be a numeric scalar') + obj.spreadAlpha = val; + obj.draw(); + end + + % get/set spread line colors + + function val = get.spreadBorderLineColor(obj) + val = obj.parseColor(obj.spreadBorderLineColor); + end + + function set.spreadBorderLineColor(obj,val) + obj.spreadBorderLineColor = val; + obj.draw(); + end + + % set spread border line width + + function set.spreadBorderLineWidth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:functionalPlot:invalidspreadBorderLineWidth', ... + '''SPREADBORDERLINEWIDTH'' must be a numeric scalar') + obj.spreadBorderLineWidth = val; + obj.draw(); + end + + % set/get spread color + + function val = get.spreadColor(obj) + val = obj.parseColor(obj.spreadColor); + end + + function set.spreadColor(obj,val) + obj.spreadColor = val; + obj.draw(); + end + + % whisker + + function set.whiskers(obj,val) + assert(islogical(val) && isscalar(val), 'iosr:functionalPlot:invalidWhiskers', ... + '''whisker'' must be a scalar and logical'); + obj.whiskers = val; + obj.draw(); + end + + end + + methods (Access = protected) + + % Draw the plot + function draw(obj) + + if isfield(obj.handles,'axes') + + axes(obj.handles.axes); + hold on; + + if length(obj.outDims) > 2 + nlines = obj.outDims(3); + else + nlines = 1; + end + for n = nlines:-1:1 + % draw inner patch + obj.handles.spreads(n) = patch(... + [obj.x obj.x(end:-1:1)], ... + [obj.statistics.inner_u(:,:,n) obj.statistics.inner_l(:,end:-1:1,n)], ... + obj.spreadColor{n} , ... + 'FaceAlpha', obj.spreadAlpha, ... + 'EdgeColor', obj.spreadBorderLineColor{n}, ... + 'LineWidth', obj.spreadBorderLineWidth ... + ); + end + + for n = nlines:-1:1 + + % draw outer limits + obj.handles.outer_u(n) = line(obj.x, obj.statistics.outer_u(:,:,n), ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n} ... + ); + obj.handles.outer_l(n) = line(obj.x, obj.statistics.outer_l(:,:,n), ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n} ... + ); + + % draw centre line + obj.handles.main(n) = line(obj.x, obj.statistics.main(:,:,n), ... + 'linestyle', obj.mainLineStyle{n}, ... + 'linewidth', obj.mainLineWidth{n}, ... + 'color', obj.mainLineColor{n} ... + ); + + end + + % draw whiskers + if obj.whiskers + x_range = max(obj.x) - min(obj.x); + whisker_xlim = [(min(obj.x) + (1/3)*x_range) (max(obj.x) - (1/3)*x_range)]; + if nlines==1 + whisker_x = mean(whisker_xlim); + else + whisker_x = linspace(whisker_xlim(1),whisker_xlim(2),nlines); + end + for n = nlines:-1:1 + % interpolate to find y + [~,x_ix] = min(abs(obj.x-whisker_x(n))); + x_interp_ix = [max(1,x_ix-1) x_ix min(length(obj.x),x_ix+1)]; + x_interp_ix = unique(x_interp_ix); + y_i_l = interp1(obj.x(x_interp_ix), obj.statistics.inner_l(:,x_interp_ix,n), whisker_x(n)); + y_i_u = interp1(obj.x(x_interp_ix), obj.statistics.inner_u(:,x_interp_ix,n), whisker_x(n)); + y_o_l = interp1(obj.x(x_interp_ix), obj.statistics.outer_l(:,x_interp_ix,n), whisker_x(n)); + y_o_u = interp1(obj.x(x_interp_ix), obj.statistics.outer_u(:,x_interp_ix,n), whisker_x(n)); + + % plot + obj.handles.whiskers_l(n) = line([whisker_x(n) whisker_x(n)],[y_i_l y_o_l], ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n}); + obj.handles.whiskers_u(n) = line([whisker_x(n) whisker_x(n)],[y_i_u y_o_u], ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n}); + end + else + try + delete(obj.handles.whiskers_l(n)) + delete(obj.handles.whiskers_u(n)) + catch + end + end + end + + end + + end + + methods (Access = protected) + + % Make properties in to a cell array + function val = parseProps(obj, prop, addP) + + nLines = obj.outDims(3); + if ~addP + nAdd = 1; + else + nAdd = length(obj.addPrctiles); + end + val = cell(nLines, nAdd); + if isnumeric(prop) + cellprop = num2cell(prop); + elseif ischar(prop) + cellprop = cellstr(prop); + else + cellprop = prop; + end + try + for n = 1:nLines + if ~addP + val(n) = cellprop(mod(n-1, numel(cellprop)) + 1); + else + for p = 1:nAdd + ixn = mod(n-1, size(cellprop, 1)) + 1; + ixp = mod(p-1, size(cellprop, 2)) + 1; + val(n,p) = cellprop(ixn, ixp); + end + end + end + catch + keyboard + end + + end + + % Put colors in to a cell array + function val = parseColor(obj, inColor) + + nLines = obj.outDims(3); + val = cell(nLines, 1); + if isnumeric(inColor) + if size(inColor, 2) ~= 3 + error('iosr:functionalPlot:colorInvalid','Color must be an N-by-3 array, where N is any positive integer.') + end + for n = 1:nLines + val(n,:) = {inColor(mod(n, size(inColor, 1)) + 1, :)}; + end + elseif ischar(inColor) + if strcmp(inColor, 'auto') + colors = lines(nLines); + for n = 1:nLines + val(n,:) = {colors(n, :)}; + end + else + colors = cellstr(inColor); + for n = 1:nLines + val(n,:) = colors(mod(n, size(inColor, 1)) + 1); + end + end + elseif isa(inColor,'function_handle') + colors = inColor(nLines); + for n = 1:nLines + val(n,:) = {colors(mod(n, numel(inColor)) + 1)}; + end + elseif iscellstr(inColor) + for n = 1:nLines + val(n,:) = inColor(mod(n, numel(inColor)) + 1); + end + else + error('iosr:functionalPlot:invalidColorFormat','Invalid color format specified.') + end + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalSpreadPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalSpreadPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..1a2f58fc3e8a0f8c884adbfac2761dcc56a0e88c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/functionalSpreadPlot.m @@ -0,0 +1,535 @@ +classdef (CaseInsensitiveProperties = true) functionalSpreadPlot < ... + iosr.statistics.functionalPlot +%FUNCTIONALSPREADPLOT Draw a functional plot showing data spread +% +% Use this class to plot the spread of data against a continuous +% variable. The class calculates point-wise statistics for each set of +% observations on the x-axis. For a plot of spread where each _function_ +% constitutes a single observation, use IOSR.STATISTICS.FUNCTIONALBOXPLOT +% instead. +% +% Measures of spread include parametric and non-parametric confidence +% intervals, interquartile range, standard deviation, or arbitrary +% percentile ranges. The spread is indicated by a shaded region, with a +% central line indicating the primary metric (mean or median). Additional +% percentiles, outliers, and the limits of the data may also be plotted. +% +% FUNCTIONALSPREADPLOT operates on the array Y, which is an N-by-M-by-P +% array, where N observations for each X value are stored in the columns +% of Y, there are M X-values, and there are P functional plots. +% +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT properties: +% addPrctiles - Plot lines for additional percentiles. +% The property should be a vector of +% percentiles; each percentile will be +% plotted for each functional plot. The +% property is empty by default. +% addPrctilesLineColor - Specify the line colors for the +% additional percentile lines. The property +% may be specified using any valid MATLAB +% color specifier. Multiple colors (for +% multiple function plots) may be specified +% by passing colors in a length-P cell +% vector, or by passing a color map +% function handle. The default is 'auto', +% which uses Matlab's 'line' color map. +% addPrctilesLineStyle - Specify the line styles for the +% additional percentile lines. The property +% may be specified as a char array (e.g. +% '-'), or as a P-by-Q cell array of +% strings, where Q is the number of +% additional percentiles. The default is +% '--'. +% addPrctilesLineWidth - Specify the line widths for the +% additional percentile lines. The property +% may be specified as a numeric array (e.g. +% '-'), or as a P-by-Q cell array, where Q +% is the number of additional percentiles. +% The default is 1. +% innerMode - Specify the mode for plotting the inner +% shaded area of the plot. The options are: +% - 'quartile' : the 25th to 75th +% percentile +% (interquartile range) +% - 'std' : the standard deviation +% - 'notch' : the non-parametric +% confidence interval (see +% iosr.statistics.boxPlot) +% - 'ci90' : the 90% confidence +% interval +% - 'ci95' : the 95% confidence +% interval +% - 'ci99' : the 99% confidence +% interval +% The default is 'quartile'. +% limit - Specifies the mode indicating the limits +% that define outliers. See +% iosr.statistics.boxPlot. The default is +% '1.5IQR'. +% mainMode - Specifies the statistic used for the +% central line. The options are 'median' or +% 'mean'. The default is 'median'. +% method - Specifies the method used to calculate +% the quantiles. See +% iosr.statistics.boxPlot. The default is +% 'R-8'. +% outerMode - Specifies what the outer lines plot. The +% options are 'limit' (plots the limits of +% the data as determined by the 'limit' +% option) or 'none'. +% outlierSize - Specifies the size, in square points, of +% the outlier markers. The default is 36. +% outlierEdgeColor - Specifies the color of the outlier marker +% edges. See 'addPrctilesLineColor' for +% details of how to specify colors. The +% default is 'auto'. +% outlierFaceColor - Specifies the color of the outlier marker +% faces. See 'addPrctilesLineColor' for +% details of how to specify colors. The +% default is 'none'. +% outlierMarker - Specifies the markers used for the +% outliers. The property may be specified +% as a char array (e.g. '+'), or as a cell +% array of strings (if passing markers for +% each functional plot). The default is +% '+'. +% +% Additional properties are inherited from +% IOSR.STATISTICS.FUNCTIONALPLOT. +% +% These properties can be referenced using dot notation - e.g. H.LIMIT +% where H is an instance of the FUNCTIONALSPREADPLOT object - or using +% the SET and GET methods - e.g. GET(H,'LIMIT'). Both methods are +% case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% Read-only properties: +% x - The x data. +% y - The y data. +% weights - Array giving the weights for the data in y. +% The array must be the same size as y. +% statistics - Structure containing the statistics used +% for the box plot. With the exception of +% 'outliers', 'outliers_IX', 'addPrctiles', and +% 'percentile' noted below, each field contains +% a 1-by-M-by-P numeric array of values +% (identical to that returned by +% IOSR.STATISTICS.QUANTILE). The fields are: +% 'addPrctiles' : an A-by-M-by-P... array +% containing the +% additional percentile +% values specified by the +% 'addPrctiles' property, +% where A is the number +% of percentiles in the +% property +% 'percentile' : the percentile limits +% specified by the +% 'percentile' property +% 'median' : the median values +% 'N' : the sample size +% 'Q1' : the 25th percentiles +% 'Q3' : the 75th percentiles +% 'inner_l' : the inner shaded area's +% lower limit +% 'inner_u' : the inner shaded area's +% upper limit +% 'IQR' : the inter-quartile +% ranges +% 'main' : the values of the +% central line +% 'mean' : the mean values +% 'min' : the minimum values +% (excl. outliers) +% 'max' : the maximum values +% (excl. outliers) +% 'notch_u' : the upper notch values +% 'notch_l' : the lower notch values +% 'outer_l' : the outer line's lower +% limit +% 'outer_u' : the outer line's upper +% limit +% 'outliers' : a 1-by-M-by-P cell +% array of outlier values +% 'outliers_IX' : a logical array, the +% same size as Y, with +% true values indicating +% outliers +% 'std' : the standard deviations +% +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT methods: +% functionalSpreadPlot - Create the plot. +% +% See also IOSR.STATISTICS.BOXPLOT, IOSR.STATISTICS.QUANTILE, +% IOSR.STATISTICS.FUNCTIONALPLOT, IOSR.STATISTICS.FUNCTIONALBOXPLOT. + + properties (AbortSet) + addPrctiles = [] % Additional percentiles to plot. + addPrctilesLineColor = 'auto' % Colors for the additional percentile lines. + addPrctilesLineStyle = '--' % Styles for the additional percentile lines. + addPrctilesLineWidth = 0.5 % Widths for the additional percentile lines. + innerMode = 'quartile' % Mode of the central shaded area. + limit = '1.5IQR' % Mode indicating the limits that define outliers. + mainMode = 'median' % The statistic used for the central line. + method = 'R-8' % The method used to calculate the quantiles. + outerMode = 'limit' % Mode of the outer lines. + outlierSize = 36 % Size of the outlier markers. + outlierEdgeColor = 'auto' % Color of the outlier marker edges. + outlierFaceColor = 'none' % Color of the outlier marker faces. + outlierMarker = '+' % The outlier marker. + end + + properties (Access = private) + data + end + + methods + + % constructor + function obj = functionalSpreadPlot(varargin) + % FUNCTIONALSPREADPLOT Draw a functional spread plot. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(Y) produces a functional + % spread plot of the data in Y. Y should be an N-by-M or + % N-by-M-by-P array, where N observations for each X value are + % stored in the columns of Y, there are M X-values, and there are + % P functional plots. The plot shows the median as the main line, + % the interquartile range as the shaded region, lines showing the + % limits of the data, and markers showing any outliers. See + % IOSR.STATISTICS.BOXPLOT for an explanation of how limits and + % outliers are estimated. This plot is traditionally known as a + % functional box plot. + % + % Tabular data can be arranged into the appropriate format using + % the IOSR.STATISTICS.TAB2BOX function. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(X,Y) specifies the x-axis + % values for the plot. X should be an M-length vector. The + % default is 1:M. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(...,'PARAMETER',VALUE) + % allows the plotting options to be specified when the plot is + % constructed. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(AX,...) creates the plot + % in the axes specified by AX. + % + % Examples + % + % Example 1: Draw a functional box plot + % % generate random data + % y = cat(3, randn(100,21), 0.25+randn(100,21)); + % x = 0:20; + % + % % Draw a functional box plot for the first function + % figure + % iosr.statistics.functionalSpreadPlot(x, y(:,:,1)); + % title('Functional box plot.') + % axis tight + % box on + % + % Example 2: Plot means and confidence intervals + % figure + % iosr.statistics.functionalSpreadPlot(x, y,... + % 'spreadAlpha',0.5,... + % 'outerMode', 'none', ... + % 'innermode', 'ci95', ... + % 'mainmode', 'mean', ... + % 'showOutliers', false); + % title('Mean and 95% confidence intervals') + % axis tight + % box on + + start = obj.getXY(varargin{:}); + + % check input is valid size + assert(ndims(obj.y) <= 3 && ndims(obj.y) >= 2, ... + 'iosr:functionalSpreadPlot:invalidY', ... + 'Y must be a two- or three-dimensional array.'); + + % check weights + obj.checkWeights(); + + % set the properties of the plot + obj.setProperties(start,nargin,varargin); + + % remove NaN columns + obj.removeNaN(); + + % calculate the statistics used in the plot + obj.calculateStats(); + + %% draw + + % set handles + obj.parseAxesHandle(varargin{:}); + + % draw the box plot + obj.draw(); + + end + + %% Accessors / Mutators + + function set.mainMode(obj, val) + obj.mainMode = val; + obj.calculateStats(); + obj.draw(); + end + + function set.innerMode(obj, val) + obj.innerMode = val; + obj.calculateStats(); + obj.draw(); + end + + function set.limit(obj, val) + obj.limit = val; + obj.calculateStats(); + obj.draw(); + end + + function set.method(obj, val) + obj.method = val; + obj.calculateStats(); + obj.draw(); + end + + function set.outerMode(obj, val) + obj.outerMode = val; + obj.calculateStats(); + obj.draw(); + end + + % additional percentiles + + function set.addPrctiles(obj, val) + if ~isempty(val) + assert(all(val >= 0) && all(val <= 1000), 'iosr:functionalSpreadPlot:invalidPrctiles', ... + 'Additional percentiles must be in the range [0, 100].') + obj.addPrctiles = val; + end + obj.calculateStats(); + obj.draw(); + end + + function val = get.addPrctilesLineColor(obj) + val = obj.parseColor(obj.addPrctilesLineColor); + end + + function set.addPrctilesLineColor(obj,val) + obj.addPrctilesLineColor = val; + obj.draw(); + end + + function val = get.addPrctilesLineStyle(obj) + val = obj.parseProps(obj.addPrctilesLineStyle, true); + end + + function set.addPrctilesLineStyle(obj,val) + obj.addPrctilesLineStyle = val; + obj.draw(); + end + + function val = get.addPrctilesLineWidth(obj) + val = obj.parseProps(obj.addPrctilesLineWidth, true); + end + + function set.addPrctilesLineWidth(obj,val) + obj.addPrctilesLineWidth = val; + obj.draw(); + end + + % outlier settings + + function set.outlierSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:functionalSpreadPlot:invalidOutlierSize', ... + '''OUTLIERSIZE'' must be a numeric scalar') + obj.outlierSize = val; + obj.draw(); + end + + function val = get.outlierEdgeColor(obj) + val = obj.parseColor(obj.outlierEdgeColor); + end + + function set.outlierEdgeColor(obj,val) + obj.outlierEdgeColor = val; + obj.draw(); + end + + function val = get.outlierFaceColor(obj) + val = obj.parseColor(obj.outlierFaceColor); + end + + function set.outlierFaceColor(obj,val) + obj.outlierFaceColor = val; + obj.draw(); + end + + function val = get.outlierMarker(obj) + val = obj.parseProps(obj.outlierMarker, false); + end + + function set.outlierMarker(obj,val) + obj.outlierMarker = val; + obj.draw(); + end + + end + + methods (Access = protected) + + % calculate the statistics used in the plot + function calculateStats(obj) + + % Most statistics are calculated in the base class + calculateStats@iosr.statistics.statsPlot(obj); + + % Calculate specific stats + outsize = size(obj.statistics.median); + obj.statistics.addPrctiles = zeros([length(obj.addPrctiles) outsize(2:end)]); + obj.statistics.main = zeros(outsize); + obj.statistics.inner_u = zeros(outsize); + obj.statistics.inner_l = zeros(outsize); + obj.statistics.outer_u = zeros(outsize); + obj.statistics.outer_l = zeros(outsize); + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(obj.outDims) + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = subidx; + subidxAll{1} = ':'; + + if isnumeric(obj.innerMode) + assert(numel(obj.innerMode) == 2, 'iosr:functionalSpreadPlot:invalidInnerMode', ... + 'If numeric, INNERMODE must be a two-element vector.') + obj.statistics.inner_u(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + max(obj.innerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + obj.statistics.inner_l(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + min(obj.innerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + else + assert(ischar(obj.innerMode), 'iosr:functionalSpreadPlot:invalidInnerMode', ... + 'INNERMODE must be numeric or a char array.') + switch obj.innerMode + case 'quartile' + obj.statistics.inner_u(subidx{:}) = obj.statistics.Q3(subidx{:}); + obj.statistics.inner_l(subidx{:}) = obj.statistics.Q1(subidx{:}); + case 'notch' + obj.statistics.inner_u(subidx{:}) = obj.statistics.notch_u(subidx{:}); + obj.statistics.inner_l(subidx{:}) = obj.statistics.notch_l(subidx{:}); + case 'std' + std = obj.statistics.std(subidx{:})/2; + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + std; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - std; + case 'ci90' + cil = ( (1.645 * obj.statistics.std(subidx{:})) / sqrt(obj.statistics.N(subidx{:})) ); + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + cil; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - cil; + case 'ci95' + cil = ( (1.96 * obj.statistics.std(subidx{:})) / sqrt(obj.statistics.N(subidx{:})) ); + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + cil; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - cil; + case 'ci99' + cil = ( (2.576 * obj.statistics.std(subidx{:})) / sqrt(obj.statistics.N(subidx{:})) ); + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + cil; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - cil; + otherwise + error('iosr:functionalSpreadPlot:unknownInnerMode','Unkonwn INNERMODE.') + end + end + + if isnumeric(obj.outerMode) + assert(numel(obj.outerMode) == 2, 'iosr:functionalSpreadPlot:invalidOuterMode', ... + 'If numeric, OUTERMODE must be a two-element vector.') + obj.statistics.outer_u(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + max(obj.outerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + obj.statistics.outer_l(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + min(obj.outerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + else + assert(ischar(obj.outerMode), 'iosr:functionalSpreadPlot:invalidOuterMode', ... + 'OUTERMODE must be numeric or a char array.') + switch obj.outerMode + case 'limit' + obj.statistics.outer_u(subidx{:}) = obj.statistics.max(subidx{:}); + obj.statistics.outer_l(subidx{:}) = obj.statistics.min(subidx{:}); + case 'none' + obj.statistics.outer_u(subidx{:}) = NaN; + obj.statistics.outer_l(subidx{:}) = NaN; + otherwise + error('iosr:functionalSpreadPlot:unknownOuterMode','Unknown OUTERMODE.') + end + end + + switch obj.mainMode + case 'mean' + obj.statistics.main(subidx{:}) = obj.statistics.mean(subidx{:}); + case 'median' + obj.statistics.main(subidx{:}) = obj.statistics.median(subidx{:}); + otherwise + error('iosr:functionalSpreadPlot:unknownMainMode','Unknown MAINMODE.') + end + + if ~isempty(obj.addPrctiles) + obj.statistics.addPrctiles(subidxAll{:}) = ... + iosr.statistics.quantile(obj.y(subidxAll{:}),obj.addPrctiles(:)./100,[],obj.method,obj.weights(subidxAll{:})); + end + + temp = obj.y(subidxAll{:}); + obj.statistics.mean(subidx{:}) = mean(temp(~isnan(temp))); + end + + end + + % Draw the plot + function draw(obj) + + if isfield(obj.handles,'axes') + + axes(obj.handles.axes); + cla; + hold on; + + if length(obj.outDims) > 2 + nlines = obj.outDims(3); + else + nlines = 1; + end + + draw@iosr.statistics.functionalPlot(obj); + + for n = nlines:-1:1 + + % draw additional percentiles + if ~isempty(obj.addPrctiles) + for p = 1:numel(obj.addPrctiles) + obj.handles.addPrctiles(p,n) = line(obj.x, squeeze(obj.statistics.addPrctiles(p,:,n)), ... + 'color', obj.addPrctilesLineColor{n}, ... + 'linewidth', obj.addPrctilesLineWidth{n,p}, ... + 'linestyle', obj.addPrctilesLineStyle{n,p}); + end + end + + % draw outliers + if (obj.showOutliers) + xOutliers = repmat(obj.x,size(obj.y, 1), 1); + xOutliers = xOutliers(obj.statistics.outliers_IX(:,:,n)); + yOutliers = obj.y(:,:,n); + yOutliers = yOutliers(obj.statistics.outliers_IX(:,:,n)); + obj.handles.outliers(n) = scatter(xOutliers, yOutliers, ... + obj.outliersize, obj.outlierMarker{n}, ... + 'MarkerEdgeColor', obj.outlierEdgeColor{n}, ... + 'MarkerFaceColor', obj.outlierFaceColor{n}, ... + 'LineWidth', obj.outlierLineWidth{n}); + end + + end + + end + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/getRmse.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/getRmse.m new file mode 100644 index 0000000000000000000000000000000000000000..4a68d864f1745b0601248f0073e3435f68b4037e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/getRmse.m @@ -0,0 +1,92 @@ +function RMSE = getRmse(X, y, varargin) +%GETRMSE Calculate the root-mean-square error between input data +% +% RMSE = IOSR.STATISTICS.GETRMSE(X, Y) calculates the RMSE of the inputs +% data where +% +% RMSE = sqrt( 1/N-D * SUM(err^2) ) +% err = abs(X-Y) +% +% The input data X and Y can be vectors or matrices; D=1. X and Y must +% have equal size. +% +% RMSE = IOSR.STATISTICS.GETRMSE(X, Y, D) allows the degrees of freedom D +% to be specified. The default is D=1 (you may wish to set it to 0, or +% the degrees of freedom). +% +% RMSEEPS = IOSR.STATISTICS.GETRMSE(X, Y, D, EPSILON) calculates +% epsilon-insensitive RMSE (RMSE*). The parameter EPSILON is a threshold +% for err values: err values less than the respective EPSILON value are +% set to 0; err values greater than EPSILON have EPSILON subtracted from +% them. This allows for the calculation of error 'after' a certain effect +% (such as subjective error). RMSEEPS will ALWAYS be lower than RMSE. The +% value of EPSILON will generally be set to half the 95% confidence +% interval or similar + +% Copyright 2016 University of Surrey. + + % test input types + assert(isnumeric(X)&isnumeric(y),'Input data must be numeric!'); + assert(length(size(X))==length(size(y)),'Input data X and y must be the same size'); + assert(all(size(X)==size(y)),'Input data X and y must be the same size'); + + % extract inputs + nInputs = (numel(varargin) + 2); + d = -1; + epsilon = -1; + epsFlag = 0; + + if nInputs == 2 + if numel(X)>1 + d = 1; + else + error('you should not calculate RMSE for a singular') + end + elseif nInputs == 3 + if ( varargin{1} < numel(X) ) + d = varargin{1}; + else + error('d cannot be larger than or equal to N'); + end + elseif nInputs == 4 + if ( varargin{1} < numel(X) ) + d = varargin{1}; + else + error('d cannot be larger than or equal to N'); + end + if ( varargin{2} >= 0) + epsilon = varargin{2}; + else + error('epsilon should not be negative!'); + end + epsFlag = 1; + elseif (nInputs<2) || (nInputs>4) + error('should be >1 and <5 input arguments') + end + + % Test RMSE == 0 when input vectors identical + assert(Calc(1:10,1:10,1,0,0)==0,'RMSE of x=Y for equal vectors does not compute correctly'); + assert(Calc(ones(3,3,3),ones(3,3,3),1,0,0)==0,'RMSE of x=Y for equal matrices does not compute correctly'); + + % Test RMSE calculated properly for dummy data + assert(Calc([1 2 3; 1 2 3; 1 2 3],[3 2 1; 3 2 1; 3 2 1],1,0,0)==(sqrt(3)),'RMSE of x=Y for dummy data does not compute correctly'); + + % Test RMSEeps calculated properly for dummy data + assert(single(Calc([1 2 3],[1.4 2.4 3.4],1,0.3,1))==single(sqrt(0.015)),'RMSE epsilon insensitive for dummy data does not compute correctly'); + assert(single(Calc([1 2 3],[1.4 2.4 3.4],1,[0.3 0.4 0.4],1))==single(sqrt(0.005)),'RMSE epsilon insensitive for dummy data does not compute correctly'); + + RMSE = Calc(X,y,d,epsilon,epsFlag); + +end + +function RMSE = Calc(X,y,d,epsilon,epsFlag) +%CALC Calculate RMSE & RMSE* + + % Calculate RMSE + err = abs(X-y); + if epsFlag + err = max(err-epsilon,0); + end + RMSE = sqrt((1/(numel(err)-d)) * sum(err(:).^2)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/kernelDensity.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/kernelDensity.m new file mode 100644 index 0000000000000000000000000000000000000000..86b108437f35a241704adec8fa7954436d6d4e2e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/kernelDensity.m @@ -0,0 +1,152 @@ +function [d, xd, bw] = kernelDensity(x, bins, h, kernel) +%KERNELDENSITY Calculate the kernel density of a data set +% +% [D, XD] = IOSR.STATISTICS.KERNELDENSITY(X) calculate the kernel density +% D of a dataset X for query points XD. The kernel density is calculated +% for 100 query points equally spaced between the minimum and maximum of +% the data X. The density is estimated using a gaussian kernel with a +% width that is optimal for normal data. X may be a vector, matrix, or +% multi-dimensional array; the entire array is treated as the sample. D +% and XD are 100-point column vectors. NaN are excluded from the +% calculations. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS) calculates the density for +% the query points specified by BINS. If BINS is a scalar, then BINS +% points are queried between MIN(X(:)) and MAX(X(:)); if BINS is a +% vector, then the values are used as the query points directly. D and XD +% are column vectors. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, H) uses the bandwidth H to +% calculate the kernel density. H must be a scalar. BINS may be an empty +% array in order to use the default described above. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, [], KERNEL) uses the +% kernel function specified by KERNEL to calculate the density. The +% kernel may be: +% - 'normal' (default), +% - 'uniform', +% - 'triangular', +% - 'epanechnikov', +% - 'quartic', +% - 'triweight', +% - 'tricube', +% - 'cosine', +% - 'logistic', +% - 'sigmoid', or +% - 'silverman'. +% For the uniform case the bandwidth is set to 15% of the range of the +% data [1]. Otherwise the bandwidth is chosen to be optimal for normal +% data assuming a gaussian kernel. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, H, KERNEL) allows the +% bins BINS and bandwidth H to be specified directly. +% +% [D, XD, BW] = IOSR.STATISTICS.KERNELDENSITY(...) returns the badwidth +% BW. +% +% Examples +% +% Example 1: Plot the kernel density of gaussian data +% figure +% % gaussian random numbers +% y = randn(100000, 1); +% % density +% [d, xd] = iosr.statistics.kernelDensity(y); +% % plot +% plot(xd, d); +% +% Example 2: Density trace with 200 bins of width of 10% of data range +% figure +% % random numbers +% y = randn(100000, 1); +% % y range +% range = max(y(:)) - min(y(:)); +% % density trace +% [d, xd] = iosr.statistics.kernelDensity(y, 200, 0.1*range, 'uniform'); +% % plot +% plot(xd, d); +% +% References +% +% [1] Hintze, Jerry L.; Nelson, Ray D. (1998). "Violin Plots: A Box +% Plot-Density Trace Synergism". The American Statistician. 52 (2): +% 181?4. + + %% input check + + x = x(:); + x = x(~isnan(x)); + assert(numel(x) > 1, 'X must be a vector, matrix, or array.') + + % x bins + if nargin < 2 + bins = []; + end + if isempty(bins) + bins = 100; + end + if isscalar(bins) + bins = linspace(min(x), max(x), round(bins)); + end + bins = bins(:); + + % bin width + if nargin < 3 + h = []; + end + + % kernel + if nargin < 4 + kernel = []; + end + if isempty(kernel) + kernel = 'normal'; + end + % return kernel function + switch lower(kernel) + case 'uniform' + K = @(u) 0.5*(abs(u) <= 1); + if isempty(h) + h = 0.15 * (max(x) - min(x)); + end + case 'normal' + K = @(u) ((1/sqrt(2*pi)) * exp(-0.5*(u.^2))); + case 'triangular' + K = @(u) ((1-abs(u)) .* (abs(u) <= 1)); + case 'epanechnikov' + K = @(u) ((0.75*(1-(u.^2))) .* (abs(u) <= 1)); + case 'quartic' + K = @(u) (((15/16)*(1-(u.^2)).^2) .* (abs(u) <= 1)); + case 'triweight' + K = @(u) (((35/32)*(1-(u.^2)).^3) .* (abs(u) <= 1)); + case 'tricube' + K = @(u) (((70/81)*(1-(abs(u).^3)).^3) .* (abs(u) <= 1)); + case 'cosine' + K = @(u) (((pi/4)*cos((pi/2)*u)) .* (abs(u) <= 1)); + case 'logistic' + K = @(u) (1 / (exp(u) + 2 + exp(-u))); + case 'sigmoid' + K = @(u) ((2/pi) * (1 / (exp(u) + exp(-u)))); + case 'silverman' + K = @(u) (0.5 * exp((-abs(u))/(sqrt(2))) .* sin((abs(u))/(sqrt(2)) + (pi/4))); + otherwise + error('Unknown kernel specified'); + end + if isempty(h) + h = ((4*(std(x).^5))/(3*numel(x))).^(1/5); + end + + assert(isscalar(h), 'h must be a scalar') + + %% calculate kernel density + + xd = sort(bins); + d = zeros(size(xd)); + + for i = 1:numel(xd) + d(i) = sum(K((x-xd(i))/h))./(numel(x)*h); + end + d(isnan(d)) = 0; + bw = h; + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/laprnd.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/laprnd.m new file mode 100644 index 0000000000000000000000000000000000000000..969e59a1845bb35cc351b9104809638614603c05 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/laprnd.m @@ -0,0 +1,38 @@ +function r = laprnd(varargin) +%LAPRND Pseudorandom numbers drawn from the Laplace distribution +% +% R = IOSR.STATISTICS.LAPRND(N) returns an N-by-N matrix containing +% pseudorandom values drawn from the Laplace distribution with mean = 0 +% and standard deviation = 1. +% +% IOSR.STATISTICS.LAPRND(M,N) or IOSR.STATISTICS.LAPRND([M,N]) returns an +% M-by-N matrix. +% +% IOSR.STATISTICS.LAPRND(M,N,P,...) or +% IOSR.STATISTICS.LAPRND([M,N,P,...]) returns an M-by-N-by-P-by-... +% array. +% +% IOSR.STATISTICS.LAPRND returns a scalar. +% +% IOSR.STATISTICS.LAPRND(SIZE(A)) returns an array the same size as A. +% +% Note: The size inputs M, N, P, ... should be nonnegative integers. +% Negative integers are treated as 0. +% +% The sequence of numbers produced by LAPRND is determined by the +% settings of the uniform random number generator that underlies RAND, +% RANDI, and RANDN. Control that shared random number generator using +% RNG. +% +% See also IOSR.STATISTICS.TRIRND, RAND, RANDN, RANDI, RNG. + +% Based on code (Matlab FE File ID: #13705) written by Elvis Chen, 2007. + +% Copyright 2016 University of Surrey. + + % Generate Laplacian noise + u = rand(varargin{:})-0.5; + b = 1/sqrt(2); + r = -b*sign(u).*log(1-(2*abs(u))); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/qqPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/qqPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..ea289df2e911b87cd776251bdec057d030546ddd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/qqPlot.m @@ -0,0 +1,173 @@ +function h = qqPlot(varargin) +%QQPLOT Quantile-quantile plot with patch option +% +% IOSR.STATISTICS.QQPLOT(Y) displays a quantile-quantile plot of the +% sample quantiles of Y versus theoretical quantiles from a normal +% distribution. If the distribution of Y is normal, the plot will be +% close to linear. +% +% IOSR.STATISTICS.QQPLOT(X,Y) displays a quantile-quantile plot of two +% samples. If the samples come from the same distribution, the plot will +% be linear. +% +% The inputs X and Y should be numeric and have an equal number of +% elements; every element is treated as a member of the sample. +% +% The plot displays the sample data with the plot symbol 'x'. +% Superimposed on the plot is a dashed straight line connecting the first +% and third quartiles. +% +% IOSR.STATISTICS.QQPLOT(...,MODE) allows the appearance of the plot to +% be configured. With MODE='line' (default), the plot appears as +% described above. With MODE='patch', the data are plotted as a patch +% object, with the area bound by the x-distribution and the linear fit +% shaded grey. With mode='both' the two appearances are combined. +% +% IOSR.STATISTICS.QQPLOT(...,MODE,METHOD) and +% IOSR.STATISTICS.QQPLOT(...,[],METHOD) allows the method for calculating +% the quartiles, used for the fit line, to be specified. The default is +% 'R-8'. Type 'help iosr.statistics.quantile' for more information. The +% latter form of the function call uses the default mode. +% +% H = IOSR.STATISTICS.QQPLOT(...) returns a two- or three-element vector +% of handles to the plotted object. The nature of the handles depends +% upon the mode. In all cases, the first handle is to the sample data, +% the second handle is to the fit line. With MODE='patch' or MODE='both', +% there is third handle to the patch object. +% +% Example +% +% % Display Q-Q plots for the rand and randn functions +% figure +% subplot(2,1,1) +% iosr.statistics.qqPlot(rand(20),'patch') +% subplot(2,1,2) +% h = iosr.statistics.qqPlot(randn(20),'patch'); +% set(h(3),'FaceColor','r') % change fill color +% +% See also IOSR.STATISTICS.QUANTILE, IOSR.STATISTICS.BOXPLOT. + +% Copyright 2016 University of Surrey. + + %% determine X and Y + + IXn = cellfun(@(x) isnumeric(x) & ~isempty(x),varargin); + + switch sum(IXn) + case 0 + error('iosr:qqPlot:noData','No input data specified') + case 1 + % compare to normal distrbution + Y = get_input_sample(varargin,IXn); + p = (.5:length(Y))/length(Y); + X = sqrt(2)*erfinv(2*p - 1); + x_label = 'Standard normal quantiles'; + y_label = 'Sample quantiles'; + case 2 + % compare to input data distribution + Y = get_input_sample(varargin,find(IXn,1,'last')); + X = get_input_sample(varargin,find(IXn,1,'first')); + assert(isequal(size(X),size(Y)), 'iosr:quantile:invalidInput', 'Input data must be the same size') + x_label = 'X quantiles'; + y_label = 'Y quantiles'; + otherwise + error('iosr:qqPlot:unkonwnInput','Unknown input specified') + end + + %% determine mode and method + + % find inputs + IXc = cellfun(@(x) ischar(x) | isempty(x),varargin); + switch sum(IXc) + case 0 + mode = []; + method = []; + case 1 + mode = varargin{IXc}; + method = []; + case 2 + mode = varargin{find(IXc,1,'first')}; + method = varargin{find(IXc,1,'last')}; + otherwise + error('iosr:qqPlot:unknownString','Unknown string specified') + end + + % defaults + if isempty(mode) + mode = 'line'; + end + if isempty(method) + method = 'R-8'; + end + + %% calculate fit to first and third quartile + + % quartiles + q1x = iosr.statistics.quantile(X,.25,[],method); + q3x = iosr.statistics.quantile(X,.75,[],method); + q1y = iosr.statistics.quantile(Y,.25,[],method); + q3y = iosr.statistics.quantile(Y,.75,[],method); + + % slope + slope = (q3y-q1y)./(q3x-q1x); + centerx = (q1x+q3x)/2; + centery = (q1y+q3y)/2; + + % fit + maxx = max(X); + minx = min(X); + maxy = centery + slope.*(maxx - centerx); + miny = centery - slope.*(centerx - minx); + + % lines + X_fit = linspace(minx,maxx,length(X)); + Y_fit = linspace(miny,maxy,length(X)); + + %% plot data + + hold on + + if strcmpi(mode,'patch') || strcmpi(mode,'both') + Hp = patch([X fliplr(X_fit)],[Y fliplr(Y_fit)],[0.5 0.5 0.5]); + set(Hp,'edgecolor','none') + else + Hp = NaN; + end + + switch lower(mode) + case 'line' + linestyle = 'xk'; + case 'patch' + linestyle = '-k'; + case 'both' + linestyle = 'xk'; + otherwise + error('iosr:qqPlot:unknownMode','Unknown mode specified') + end + + H = plot(X,Y,linestyle,X_fit,Y_fit,'--k'); + + hold off + + % axis labels + xlabel(x_label) + ylabel(y_label) + + box on; axis tight + set(gca,'layer','top') + + % return handle + if nargout>0 + h = H; + if isobject(Hp) || ishandle(Hp) + h = [h; Hp]; + end + end + +end + +function Z = get_input_sample(z,IX) +%GET_INPUT_SAMPLE get sample, order, and convert to vector + Z = z{IX}; + Z = sort(Z(:))'; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/quantile.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/quantile.m new file mode 100644 index 0000000000000000000000000000000000000000..9ea308228318bebd69947f227e4b9148fb08d46e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/quantile.m @@ -0,0 +1,234 @@ +function [q,N] = quantile(X,p,dim,method,weights) +%QUANTILE Quantiles of a sample via various methods. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P) returns quantiles of the values in X. +% P is a scalar or a vector of cumulative probability values. When X is +% a vector, Q is the same size as P, and Q(i) contains the P(i)-th +% quantile. When X is a matrix, the i-th row of Q contains the P(i)-th +% quantiles of each column of X. For N-D arrays, +% IOSR.STATISTICS.QUANTILE operates along the first non-singleton +% dimension. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,DIM) calculates quantiles along +% dimension DIM. The DIM'th dimension of Q has length LENGTH(P). +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,DIM,METHOD) calculates quantiles using +% one of the methods described in http://en.wikipedia.org/wiki/Quantile. +% The method are designated 'R-1'...'R-9'; the default is R-8 as +% described in http://bit.ly/1kX4NcT, whereas Matlab uses 'R-5'. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,[],METHOD) uses the specified METHOD, +% but calculates quantiles along the first non-singleton dimension. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,[],METHOD,WEIGHTS) and +% IOSR.STATISTICS.QUANTILE(X,P,[],[],WEIGHTS) uses the array WEIGHTS to +% weight the values in X when calculating quantiles. If no weighting is +% specified, the method determines the real-valued index in to the data +% that is used to calculate the P(i)-th quantile. When a weighting array +% WEIGHTS is specified (WEIGHTS should be the same size as X), this index +% is mapped to the cumulative weights (the weights are scaled to sum to +% N(i) - see below), and a new weighted index is returned (using linear +% interpolation) for the point where the cumulative weights equal the +% unweighted index. The weighted index is used to calculate the P(i)-th +% quantile. If the values in WEIGHTS are equal, then the weighted and +% unweighted index (and correpsonding quantile) are identical. The +% default method R-8 is used if METHOD is specified as an empty array +% ([]). +% +% [Q,N] = IOSR.STATISTICS.QUANTILE(...) returns an array that is the same +% size as Q such that N(i) is the number of points used to calculate +% Q(i). +% +% Further reading +% +% Hyndman, R.J.; Fan, Y. (November 1996). "Sample Quantiles in +% Statistical Packages". The American Statistician 50 (4): 361-365. +% Frigge, Michael; Hoaglin, David C.; Iglewicz, Boris (February 1989). +% "Some Implementations of the Boxplot". The American Statistician 43 +% (1): 50-54. +% +% See also QUANTILE. + +% Copyright 2016 University of Surrey. + + %% Check input and make default assignments + + assert(isnumeric(X), 'iosr:quantile:invalidX', 'X must be a numeric'); + assert(isvector(p) & isnumeric(p), 'iosr:quantile:invalidP', 'P must be a numeric vector'); + assert(all(p>=0 & p<=1), 'iosr:quantile:invalidP', 'Values in P must be in the interval [0,1].') + + if nargin<2 + error('iosr:quantile:tooFewInputArgs','Not enough input arguments.') + end + + dims = size(X); + if nargin<3 || isempty(dim) + dim = find(dims>1,1,'first'); % default dim + else % validate input + assert(isnumeric(dim) | isempty(dim), 'iosr:quantile:invalidDim', 'DIM must be an integer or empty'); + assert(isint(dim) | isempty(dim), 'iosr:quantile:invalidDim', 'DIM must be an integer or empty'); + assert(dim>0, 'iosr:quantile:invalidDim', 'DIM must be greater than 0') + end + + if nargin<4 + method = 'r-8'; % default method + else % validate input + if isempty(method) + method = 'r-8'; % default method + else + assert(ischar(method), 'iosr:quantile:invalidMethod', 'METHOD must be a character array') + end + end + + if nargin<5 + weights = []; + else + assert(isequal(size(X),size(weights)) || isempty(weights), 'iosr:quantile:invalidWeights', 'WEIGHTS must be the same size as X'); + end + + %% choose method + + % See http://en.wikipedia.org/wiki/Quantile#Estimating_the_quantiles_of_a_population + + switch lower(method) + case 'r-1' + min_con = @(N,p)(p==0); + max_con = @(N,p)(false); + h = @(N,p)((N*p)+.5); + Qp = @(x,h)(x(ceil(h-.5))); + case 'r-2' + min_con = @(N,p)(p==0); + max_con = @(N,p)(p==1); + h = @(N,p)((N*p)+.5); + Qp = @(x,h)((x(ceil(h-.5))+x(floor(h+.5)))/2); + case 'r-3' + min_con = @(N,p)(p<=(.5/N)); + max_con = @(N,p)(false); + h = @(N,p)(N*p); + Qp = @(x,h)(x(round(h))); + case 'r-4' + min_con = @(N,p)(p<(1/N)); + max_con = @(N,p)(p==1); + h = @(N,p)(N*p); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-5' + min_con = @(N,p)(p<(.5/N)); + max_con = @(N,p)(p>=((N-.5)/N)); + h = @(N,p)((N*p)+.5); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-6' + min_con = @(N,p)(p<(1/(N+1))); + max_con = @(N,p)(p>=(N/(N+1))); + h = @(N,p)((N+1)*p); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-7' + min_con = @(N,p)(false); + max_con = @(N,p)(p==1); + h = @(N,p)(((N-1)*p)+1); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-8' + min_con = @(N,p)(p<((2/3)/(N+(1/3)))); + max_con = @(N,p)(p>=((N-(1/3))/(N+(1/3)))); + h = @(N,p)(((N+(1/3))*p)+(1/3)); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-9' + min_con = @(N,p)(p<((5/8)/(N+.25))); + max_con = @(N,p)(p>=((N-(3/8))/(N+.25))); + h = @(N,p)(((N+.25)*p)+(3/8)); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + otherwise + error('iosr:quantile:unknownMethod',['Method ''' method ''' does not exist']) + end + + %% calculate quartiles + + % reshape data so function works down columns + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x = rearrange(X,order,[dims_shift(1) prod(dims_shift(2:end))]); + if ~isempty(weights) + weights = rearrange(weights,order,[dims_shift(1) prod(dims_shift(2:end))]); + cumwfunc = @accumulateWeights; + wfunc = @weightedIndex; + else + cumwfunc = @(~,~,~,N) 1:N; + wfunc = @(x,~) x; + end + + % pre-allocate q + q = zeros([length(p) prod(dims_shift(2:end))]); + N = zeros([length(p) prod(dims_shift(2:end))]); + for m = 1:length(p) + for n = 1:numel(q)/length(p) + [xSorted,ind] = sort(x(~isnan(x(:,n)),n)); % sort + N(m,n) = length(xSorted); % sample size + k = cumwfunc(weights,ind,n,N(m,n)); + switch N(m,n) + case 0 + q(m,n) = NaN; + case 1 + q(m,n) = xSorted; + otherwise + if min_con(N(m,n),p(m)) % at lower limit + q(m,n) = xSorted(1); + elseif max_con(N(m,n),p(m)) % at upper limit + q(m,n) = xSorted(N(m,n)); + else % everything else + huw = h(N(m,n),p(m)); % unweighted index + hw = wfunc(huw,k); + q(m,n) = Qp(xSorted,hw); + end + end + end + end + + % restore dims of q to equate to those of input + q = irearrange(q,order,[length(p) dims_shift(2:end)]); + N = irearrange(N,order,[length(p) dims_shift(2:end)]); + + % if q is a vector, make same shape as p + if numel(p)==numel(q) + q=reshape(q,size(p)); + N=reshape(N,size(p)); + end + +end + +function cumweights = accumulateWeights(weights,ind,n,N) +%ACCUMULATEWEIGHTS accumulate the weights + + wSorted = weights(ind,n); % sort weights + wSorted = wSorted*N/sum(wSorted); % normalize weights to sum to N + cumweights = cumsum(wSorted); % cumulative weights + +end + +function hw = weightedIndex(huw, cumweights) +%WEIGHTEDINDEX calculate index from cumulative weights + + ii = find(sign(cumweights-huw)<0,1,'last'); + jj = find(sign(cumweights-huw)>0,1,'first'); + if isempty(ii) || isempty(jj) + hw = huw; + else + hw = ii + (huw-cumweights(ii))/(cumweights(jj)-cumweights(ii)); % weighted index + end + +end + +function y = isint(x) +%ISINT check if input is whole number + y = x==round(x); +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/statsPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/statsPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..fe5e73ae77169f3c8d1c7851fdac88356e16132b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/statsPlot.m @@ -0,0 +1,232 @@ +classdef (Abstract, CaseInsensitiveProperties = true) statsPlot < ... + matlab.mixin.SetGet +%STATSPLOT An abstract superclass for classes that plot statistics +% +% As an abstract class, this class cannot be instantiated. It provides no +% public methods. The class is a super class for: +% - iosr.statistics.boxPlot +% - iosr.statistics.functionalPlot + + properties (AbortSet) + handles = struct % Structure containing handles to plot objects. + end + + properties (SetAccess = protected) + x % The x data. + y % The y data. + weights = []; % The weights for y. + statistics = struct % Structure containing the statistics used for the plot. + end + + properties (Access = protected) + outDims % dimensions of output + ydims % dimensions of y + end + + properties (SetAccess = protected, Dependent, Hidden) + axes = [] % The parent axes of the plot. + fig = [] % The parent figure of the plot. + end + + methods + + % these are all deprecated and the handles moved to the obj.handles struct + + function val = get.axes(obj) + warning('iosr:statsPlot:deprecatedProp','''obj.axes'' is deprecated. Use ''obj.handles.axes'' instead.'); + val = obj.handles.axes; + end + + function val = get.fig(obj) + warning('iosr:statsPlot:deprecatedProp','''obj.fig'' is deprecated. Use ''obj.handles.fig'' instead.'); + val = obj.handles.fig; + end + + end + + methods (Access = protected) + + % set plot properties + function setProperties(obj,start,ngin,vgin) + + % read parameter/value inputs + if start < ngin % if parameters are specified + nArgs = length(vgin)-start+1; + if round(nArgs/2)~=nArgs/2 + error('iosr:statsPlot:nameValuePairs','Properties must be propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(vgin(start:end),2,[]) % pair is {propName;propValue} + obj.(pair{1}) = pair{2}; + end + end + + end + + function axSet = parseAxesHandle(obj, varargin) + ax = []; + axValid = false; + axSet = false; + if ((isscalar(varargin{1}) && ishghandle(varargin{1},'axes')) ... + || isa(varargin{1},'matlab.graphics.axis.AbstractAxes')) + axSet = true; + ax = handle(varargin{1}); + if isvalid(varargin{1}(1)) + axValid = true; + end + end + if nargout < 1 + if axSet + if axValid + obj.handles.axes = ax; + axes(obj.handles.axes); %#ok<CPROPLC> + obj.handles.fig = ancestor(obj.handles.axes, 'figure'); + else + error('iosr:statsPlot:axisInvalid','Axes handle is invalid.') + end + else + obj.handles.axes = newplot; + obj.handles.fig = gcf; + end + end + end + + % Get X and Y data from input + function start = getXY(obj,varargin) + + if length(varargin) > 1 + axSet = obj.parseAxesHandle(varargin{:}); + if axSet + skip = 1; + else + skip = 0; + end + if isnumeric(varargin{2+skip}) + obj.x = varargin{1+skip}; + obj.y = varargin{2+skip}; + start = 3+skip; + else + obj.y = varargin{1+skip}; + obj.x = 1:size(obj.y,2); + start = 2+skip; + end + else + obj.y = varargin{1}; + obj.x = 1:size(obj.y,2); + start = 1; + end + + if size(obj.y,1)==1 + error('iosr:statsPlot:invalidInput','Data are plotted for each column. Each column in the input has only one data point.') + end + + % check x/y data + assert(isvector(obj.x), 'iosr:statsPlot:invalidX', 'x must be a vector'); + assert(isnumeric(obj.y), 'iosr:statsPlot:invalidY', 'y must be a numeric column vector or matrix'); + assert(numel(obj.x)==size(obj.y,2), 'iosr:statsPlot:invalidInput', 'x must have the same number of elements as y has columns') + + % size of input + obj.ydims = size(obj.y); + obj.outDims = obj.ydims; obj.outDims(1) = 1; + + if length(obj.outDims) < 3 + obj.outDims = [obj.outDims 1]; + end + + end + + % Check the weights are the correct size, or set the weights to 1 + % if no weights are provided + function checkWeights(obj) + + if isempty(obj.weights) + obj.weights = ones(size(obj.y)); + else + assert(isequal(size(obj.y),size(obj.weights)), 'iosr:statsPlot:invalidWeights', 'weights must be the same size as y') + end + + end + + % Remove NaNs + function removeNaN(obj) + + % remove NaN columns + if isnumeric(obj.x) + obj.x = obj.x(~isnan(obj.x)); + obj.y = obj.y(:,~isnan(obj.x),:); + obj.y = reshape(obj.y,obj.ydims); + if ~isempty(obj.weights) + obj.weights = obj.weights(:,~isnan(obj.x),:); + obj.weights = reshape(obj.weights,obj.ydims); + end + end + + end + + % calculate the statistics for the plot + function calculateStats(obj) + + % calculate stats + obj.statistics.median = iosr.statistics.quantile(obj.y,.5,[],obj.method,obj.weights); % median + outsize = size(obj.statistics.median); + obj.statistics.mean = zeros(outsize); % sample mean + obj.statistics.std = zeros(outsize); % sample standard deviation + obj.statistics.N = zeros(outsize); % sample size + obj.statistics.Q1 = zeros(outsize); % lower quartile + obj.statistics.Q3 = zeros(outsize); % upper quartile + obj.statistics.IQR = zeros(outsize); % inter-quartile range + obj.statistics.notch_u = zeros(outsize); % high notch value + obj.statistics.notch_l = zeros(outsize); % low notch value + obj.statistics.min = zeros(outsize); % minimum (excluding outliers) + obj.statistics.max = zeros(outsize); % maximum (excluding outliers) + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(obj.outDims) + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = subidx; + subidxLogical = subidx; + subidxAll{1} = ':'; + [~,obj.statistics.N(subidx{:})] = iosr.statistics.quantile(obj.y(subidxAll{:}),0.25,[],obj.method,obj.weights(subidxAll{:})); + temp = obj.y(subidxAll{:}); + weights_temp = obj.weights(subidxAll{:}); + ix = ~isnan(temp) & ~isnan(weights_temp); + temp = temp(ix); + weights_temp = weights_temp(ix); + weights_temp = weights_temp./sum(weights_temp); + obj.statistics.mean(subidx{:}) = sum(temp .* weights_temp); + obj.statistics.std(subidx{:}) = std(temp); + obj.statistics.Q1(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),0.25,[],obj.method,obj.weights(subidxAll{:})); + obj.statistics.Q3(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),0.75,[],obj.method,obj.weights(subidxAll{:})); + obj.statistics.IQR(subidx{:}) = obj.statistics.Q3(subidx{:})-obj.statistics.Q1(subidx{:}); + obj.statistics.notch_u(subidx{:}) = obj.statistics.median(subidx{:})+(1.58*obj.statistics.IQR(subidx{:})/sqrt(obj.statistics.N(subidx{:}))); + obj.statistics.notch_l(subidx{:}) = obj.statistics.median(subidx{:})-(1.58*obj.statistics.IQR(subidx{:})/sqrt(obj.statistics.N(subidx{:}))); + if isnumeric(obj.limit) + upper_limit = iosr.statistics.quantile(obj.y(subidxAll{:}),max(obj.limit)/100,[],obj.method,obj.weights(subidxAll{:})); + lower_limit = iosr.statistics.quantile(obj.y(subidxAll{:}),min(obj.limit)/100,[],obj.method,obj.weights(subidxAll{:})); + else + switch lower(obj.limit) + case '1.5iqr' + upper_limit = obj.statistics.Q3(subidx{:})+1.5*obj.statistics.IQR(subidx{:}); + lower_limit = obj.statistics.Q1(subidx{:})-1.5*obj.statistics.IQR(subidx{:}); + case '3iqr' + upper_limit = obj.statistics.Q3(subidx{:})+3*obj.statistics.IQR(subidx{:}); + lower_limit = obj.statistics.Q1(subidx{:})-3*obj.statistics.IQR(subidx{:}); + case 'none' + upper_limit = Inf; + lower_limit = -Inf; + otherwise + error('iosr:statsPlot:unknownLimit','Unknown ''limit'': ''%s''',obj.limit) + end + end + obj.statistics.outliers_IX(subidxAll{:}) = obj.y(subidxAll{:})>upper_limit | obj.y(subidxAll{:})<lower_limit; + subidxLogical{1} = ~obj.statistics.outliers_IX(subidxAll{:}); + obj.statistics.min(subidx{:}) = min(min(obj.y(subidxLogical{:})),obj.statistics.Q1(subidx{:})); % min excl. outliers but not greater than lower quartile + obj.statistics.max(subidx{:}) = max(max(obj.y(subidxLogical{:})),obj.statistics.Q3(subidx{:})); % max excl. outliers but not less than upper quartile + subidxLogical{1} = obj.statistics.outliers_IX(subidxAll{:}); + obj.statistics.outliers{subidx{:}} = obj.y(subidxLogical{:}); + end + + end + + end + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/tab2box.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/tab2box.m new file mode 100644 index 0000000000000000000000000000000000000000..89ff2471d2fa856e5b975e37bc11f930680bf8f9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/tab2box.m @@ -0,0 +1,171 @@ +function [y,x,g] = tab2box(Xin,Yin,Gin) +%TAB2BOX Prepare tabular data for boxPlot function +% +% Y = IOSR.STATISTICS.TAB2BOX(XIN,YIN) prepares data, in tabular form, +% for use in the BOX_PLOT function. Specifically, XIN and YIN are vectors +% (for example column vectors from a results table). Y is an N-by-P +% numeric array, where P is the number of unique elements in XIN, and N +% is the maximum number of occurences of any individual element of XIN. +% In cases where elements in XIN do not occur an equal number of times, +% columns in YIN are padded with NaNs. +% +% Y = IOSR.STATISTICS.TAB2BOX(XIN,YIN,GIN) returns an +% N-by-P-by-G-by-I-by-J... numeric array, where G is the number of unique +% elements in the first column of GIN, I is the number of unique elements +% in the second column of GIN, etc. GIN is a numeric or cell matrix with +% as many rows as XIN or YIN. The input facilitates hierarchical grouping +% of the data in the box plot, with the grouping order determined by the +% column order of GIN. +% +% [Y,X] = IOSR.STATISTICS.TAB2BOX(...) returns the unique values in XIN +% to X. +% +% [Y,X,G] = IOSR.STATISTICS.TAB2BOX(...) returns the unique values in GIN +% to G. G is a cell vector whereby the Nth element contains a vector of +% length SIZE(Y,N+2). +% +% Example +% +% % Prepare data for box_plot grouped by two variables +% +% % load data +% % (requires Statistics or Machine Learning Toolbox) +% load carbig +% +% % arrange data +% [y,x,g] = iosr.statistics.tab2box(Cylinders,MPG,when); +% +% % sort +% IX = [1 3 2]; % order +% g = g{1}(IX); +% y = y(:,:,IX); +% +% % plot +% figure +% h = iosr.statistics.boxPlot(x,y,... +% 'boxColor','auto','medianColor','k',... +% 'scalewidth',true,'xseparator',true,... +% 'groupLabels',g,'showLegend',true); +% box on +% title('MPG by number of cylinders and period') +% xlabel('Number of cylinders') +% ylabel('MPG') +% +% See also IOSR.STATISTICS.BOXPLOT. + +% Copyright 2016 University of Surrey. + + %% validate input + + % validate Xin + if ischar(Xin) + Xin = cellstr(Xin); + end + assert(isvector(Xin), 'iosr:tab2box:invalidInput', 'Xin must be a vector') + + % validate Yin + assert(isvector(Yin), 'iosr:tab2box:invalidInput', 'Yin must be a vector') + assert(isnumeric(Yin), 'iosr:tab2box:invalidInput', 'Yin must be numeric') + + % validate Gin + if nargin<3 + Gin = []; + else + if ischar(Gin) + Gin = cellstr(Gin); + end + assert(isvector(Gin) || size(Gin,1)==numel(Yin), 'iosr:tab2box:invalidInput', 'Gin must be a vector or a matrix with as many rows as Y has elements.') + if isvector(Gin) + Gin = Gin(:); + end + end + + %% group + + % unique values + x = getUniques(Xin); + if iscell(x) + x = x{1}; + end + g = getUniques(Gin); + if ~iscell(g) + temp = cell(1,size(g,2)); + for c = 1:size(g,2); + temp{c} = g(:,c); + end + g = temp; + end + + % preallocate cell array + gdims = cellfun(@length,g); + dims = [1,length(x),gdims]; + yc = cell(dims); + subgidx = cell(1,length(gdims)); + + % put data into cells + for a = 1:length(x) + IXx = findIX(Xin,x,a); + for b = 1:prod(gdims) + [subgidx{:}] = ind2sub(gdims, b); % get group index + subidx = [{1} {a} subgidx{:}]; % make main index + IXg = true(size(Xin)); % select everything at first + for c = 1:length(subgidx) % narrow it down + IXg = IXg & findIX(Gin(:,c),g{c},subgidx{c}); + end + % return y as column + yc{subidx{:}} = reshape(Yin(IXx & IXg),sum(IXx & IXg),1); + end + end + + %% convert to numeric array + + try % see if can concat directly + y = cell2mat(yc); + catch % else pad with NaNs + maxSizeY = max(cellfun(@length,yc(:))); + for a = 1:numel(yc) + if length(yc{a}) < maxSizeY + yc{a} = [yc{a}; NaN(maxSizeY-length(yc{a}),1)]; + end + end + y = cell2mat(yc); + end + +end + +function IX = findIX(L,l,n) +%FINDIX find entry in array from lookup array and index + + if iscellstr(L) + IX = strcmp(L,l{n}); + elseif iscell(L) + IX = cell2mat(L)==l(n); + else + IX = L==l(n); + end +end + +function out = getUniques(d) +%GETUNIQUES return unique entries from vector + + if isvector(d) % ensure column vector + d = d(:); + end + dims = zeros(1,size(d,2)); + u = cell(1,size(d,2)); + % put unique values into columns + for c = 1:size(d,2) + if iscellstr(d(:,c)) || isnumeric(d(:,c)) + u{c} = unique(d(:,c)); + else + u{c} = unique(cell2mat(d(:,c))); + end + dims(c) = length(u{c}); + end + try % to make a numeric array + out = cell2mat(u); + catch % keep as cell array + out = u; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/trirnd.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/trirnd.m new file mode 100644 index 0000000000000000000000000000000000000000..9ecfb15a4dc44091c984741b164a8a2ab6aa2b0a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+statistics/trirnd.m @@ -0,0 +1,38 @@ +function r = trirnd(varargin) +%TRIRND Pseudorandom numbers drawn from the triangular distribution +% +% R = IOSR.STATISTICS.TRIRND(N) returns an N-by-N matrix containing +% pseudorandom values drawn from the triangular distribution constrained +% to (-1,1) and mode = 0. +% +% IOSR.STATISTICS.TRIRND(M,N) or IOSR.STATISTICS.TRIRND([M,N]) returns an +% M-by-N matrix. +% +% IOSR.STATISTICS.TRIRND(M,N,P,...) or +% IOSR.STATISTICS.TRIRND([M,N,P,...]) returns an M-by-N-by-P-by-... +% array. +% +% IOSR.STATISTICS.TRIRND returns a scalar. +% +% TRIRND(SIZE(A)) returns an array the same size as A. +% +% Note: The size inputs M, N, P, ... should be nonnegative integers. +% Negative integers are treated as 0. +% +% The sequence of numbers produced by TRIRND is determined by the +% settings of the uniform random number generator that underlies RAND, +% RANDI, and RANDN. Control that shared random number generator using +% RNG. +% +% See also IOSR.STATISTICS.LAPRND, RAND, RANDN, RANDI, RNG. + +% Based on code (Matlab FE File ID: #13705) written by Elvis Chen, 2007. + +% Copyright 2016 University of Surrey. + + % Generate traingular noise + u1 = rand(varargin{:})-0.5; + u2 = rand(varargin{:})-0.5; + r = u1+u2; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/buildSvnProfile.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/buildSvnProfile.m new file mode 100644 index 0000000000000000000000000000000000000000..0544208b56b69b810606bebace6ec91094a23a2c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/buildSvnProfile.m @@ -0,0 +1,109 @@ +function [svn_profile,svn_str] = buildSvnProfile(folders,keywords,strs,rec) +%BUILDSVNPROFILE Read data from files tagged with SVN keywords +% +% This function extracts SVN keyword data from specified files, and +% returns the filename, path and keyword data to a cell array (and +% optional char array). +% +% Keyword data are placed in files automatically by Subversion at each +% commit using the 'keyword' function. The data can be useful in +% maintaining an audit trail, or establishing the version used to +% generate a particular set of results. +% +% SVN_PROFILE = IOSR.SVN.BUILDSVNPROFILE(FOLDERS,KEYWORDS) returns a cell +% array SVN_PROFILE containing data associated with the SVN keywords +% KEYWORDS. The function will search through files contained in folders. +% +% SVN_PROFILE is a two dimensional cell array; there is one row for each +% file found in FOLDERS, and N columns: one each for the full path for +% the file, and appended columns for each specified keyword in KEYWORDS. +% Data are only returned for files that contain the specified keyword(s). +% An empty cell array, 0-by-2, is returned if no keywords are found. +% +% SVN_PROFILE = IOSR.SVN.BUILDSVNPROFILE(FOLDERS,KEYWORDS,STRS) allows +% additional filter strings STRS to be specified. See +% IOSR.GENERAL.GETCONTENTS for details of permitted filter strings. +% +% ... = IOSR.SVN.BUILDSVNPROFILE(FOLDERS,KEYWORDS,STRS,REC), with REC = +% true, allows folders to be searched recursively (default is false). +% +% [SVN_PROFILE,SVN_STR] = IOSR.SVN.BUILDSVNPROFILE(...) outputs a char +% array SVN_STR of the profile, with columns concatenated to produce +% continuous lines. Spaces are inserted to ensure that columns are +% aligned (in a monospaced font). The array is appropriate for printing +% or writing to a text file, for example. The char array can be written +% to a text file with the following command: +% +% dlmwrite('svn_profile.txt',svn_str,'delimiter','') +% +% FOLDERS, KEYWORDS,and STRS may be a char array specifying a single +% occurrence, or a cell array of strings specifying multiple occurrences. +% +% See also IOSR.SVN.READSVNKEYWORD, IOSR.GENERAL.GETCONTENTS. + +% Copyright 2016 University of Surrey. + + if ischar(folders) + folders = cellstr(folders); + end + + if ischar(keywords) + keywords = cellstr(keywords); + end + + if nargin > 2 + if ischar(strs) + strs = cellstr(strs); + end + else + strs = {'files'}; + end + + % add subfolders if recursion is requested + if nargin > 3 + if rec + for f = folders + folders = [folders; iosr.general.getContents(char(f),'filter','folders','rec',true,'path','full')]; %#ok<AGROW> + end + end + end + + keydata = cell(0,1+length(keywords)); % empty cell array to be appended + n = 1; + for f = 1:length(folders) + folder = folders{f}; + for s = 1:length(strs) + str = strs{s}; + [files,dirflag] = iosr.general.getContents(folder,'filter',str,'path','full'); % find relevant files + files = files(~dirflag); % ignore directories + if ~isempty(files) + for h = 1:length(files) + file = files{h}; + % extract keyword data from file + for k = 1:length(keywords) + keyword = keywords{k}; + keydata{n,1} = file; + keydata{n,1+k} = iosr.svn.readSvnKeyword(file,keyword); + end + n = n+1; + end + end + end + end + + % remove files where no keyword is found + IX = true(size(keydata(:,2))); + for k = 1:length(keywords) + IX = IX & cellfun(@isempty,keydata(:,1+k)); + end + svn_profile = keydata(~IX,:); + + % Build char array version of data + space = repmat(' ',size(svn_profile(:,1))); % spaces to insert between columns + svn_str = char(svn_profile(:,1)); % first column (file path) + % append keyword columns: + for k = 1:length(keywords) + svn_str = [svn_str space char(svn_profile(:,1+k))]; %#ok<AGROW> + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/headRev.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/headRev.m new file mode 100644 index 0000000000000000000000000000000000000000..371430c5f64e5f191de345081007fb8645bdfa7e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/headRev.m @@ -0,0 +1,82 @@ +function [rev,file] = headRev(folders,strs,rec) +%HEADREV Retrieve the head revision for specified files +% +% This function finds the most recently committed file in the specified +% folders(s) and returns its revision and filename. The files must +% contain the 'Revision' and 'Date' keywords. +% +% REV = IOSR.SVN.HEADREV(FOLDERS) returns the head revision (i.e. the +% highest revision) for all files in FOLDERS. +% +% REV = IOSR.SVN.HEADREV(FOLDERS,STRS) allows additional filter strings +% STRS to be specified. See GETCONTENTS for details of permitted filter +% strings. +% +% REV = IOSR.SVN.HEADREV(FOLDERS,STRS,REC), with REC = true, allows +% folders to be searched recursively (default is false). +% +% [REV,FILE] = IOSR.SVN.HEADREV(...) returns the filename to FILE of the +% file with the highest revision. +% +% FOLDERS and STRS may be a string specifying a single occurrence, or a +% cell array of strings specifying multiple occurrences. This function +% requires that the 'Revision' keyword is used in the searched functions. +% +% Note that if the folders include files from an externally-defined +% repository (which has been updated more recently than the native +% repository), a misleading revision number may be presented. +% +% See also IOSR.GENERAL.GETCONTENTS, IOSR.SVN.BUILDSVNPROFILE, +% IOSR.SVN.READSVNKEYWORD. + +% Copyright 2016 University of Surrey. + + keyword = 'Date'; % use this data to sort files (doubtful that any others would work, without considerable parsing) + + if ischar(folders) + folders = cellstr(folders); + end + + if nargin > 1 + if ischar(strs) + strs = cellstr(strs); + end + if isempty(strs) + strs = {'files'}; + end + else + strs = {'files'}; + end + + % add subfolders if recursion is requested + if nargin > 2 + if rec + for f = folders + folders = [folders; iosr.general.getContents(char(f),'filter','folders','rec',true,'path','full')]; %#ok<AGROW> + end + end + end + + % get revision info for files + svn_profile = iosr.svn.buildSvnProfile(folders,keyword,strs); + + % remove the keyword and convert revision strings to numbers + svn_profile(:,2) = cellfun(@(x) (x(length(keyword)+3:end)),svn_profile(:,2),'uni',false); + + % remove NaN (files that don't have the revision keyword) + IX1 = cellfun(@isempty,svn_profile(:,2)); + svn_profile = svn_profile(~IX1,:); + + % sort by revision number + [~,IX2] = sort(svn_profile(:,2)); + svn_profile = svn_profile(IX2,:); + + % get highest revision number + rev = iosr.svn.readSvnKeyword(svn_profile{end,1},'Revision'); + + % return corresponding filename, if requested + if nargout>1 + file = svn_profile{end,1}; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/readSvnKeyword.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/readSvnKeyword.m new file mode 100644 index 0000000000000000000000000000000000000000..97e86a012486cf4b586ea89e3c58b3a7ac5728e1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/+svn/readSvnKeyword.m @@ -0,0 +1,59 @@ +function keydata = readSvnKeyword(filename,keyword,crop) +%READSVNKEYWORD Read data from a file tagged with an SVN keyword +% +% The function takes an input filename and searches that file for a +% Subversion keyword. The data associated with the keyword are returned +% in a character array. Keyword data are placed in files automatically by +% Subversion at each commit using the 'keyword' function. The data can be +% useful in maintaining an audit trail, or establishing the version used +% to generate a particular set of results. +% +% KEYDATA = IOSR.SVN.READSVNKEYWORD(FILENAME,KEYWORD) returns a string +% KEYDATA containing data associated with the SVN keyword KEYWORD in a +% file specified by FILENAME. +% +% FILENAME and KEYWORD must be strings specifying a single file and +% keyword respectively. To read multiple files or use multiple keywords, +% use BUILD_SVN_PROFILE instead. The function returns an empty string if +% the keyword is not found. +% +% KEYDATA = IOSR.SVN.READSVNKEYWORD(FILENAME,KEYWORD,CROP), with CROP = +% true (default is false), removes the keyword, and leading and trailing +% spaces, from the returned string. +% +% See also IOSR.SVN.BUILDSVNPROFILE. + +% Copyright 2016 University of Surrey. + + + assert(ischar(filename) & ischar(keyword), 'iosr:readSvnKeyword:invalidInputs', 'FILENAME and KEYWORD must be char arrays') + + if nargin < 3 + crop = false; + end + + keydata = ''; + + fid = fopen(filename); % open file + assert(fid~=-1, 'iosr:readSvnKeyword:invalidFile', ['read_svn_keyword: ''' filename ''' not found']) + + tline = fgetl(fid); % read first line + while ischar(tline) + k1 = strfind(tline,['$' keyword ':']); % find keyword + if ~isempty(k1) % if it is found + k2 = strfind(tline,'$'); % find the end of the keyword data + k2 = k2(k2>k1); + keydata = tline(k1+1:k2-2); % extract the data from the line + tline = -1; % set tline to numeric + else + tline = fgetl(fid); % read next line + end + end + + if crop + keydata = keydata(find(isspace(keydata),1,'first')+1:end); + end + + fclose(fid); % close file + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/Contents.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/Contents.m new file mode 100644 index 0000000000000000000000000000000000000000..426bbfadea3996d0bc278cad1e32465891918b32 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/Contents.m @@ -0,0 +1,98 @@ +% +IOSR +% +% Contents file for +IOSR and its subfolders. +% +% +IOSR +% iosr.install - Set search paths, and download and install dependencies +% +% +IOSR/+ACOUSTICS +% iosr.acoustics.irStats - Calculate RT, DRR, Cte, and EDT for impulse response file +% iosr.acoustics.rtEst - Estimate reverberation time based on room size and absorption +% +% +IOSR/+AUDITORY +% iosr.auditory.azimuth2itd - Convert azimuth in degrees to ITD +% iosr.auditory.binSearch - Conduct a binary search +% iosr.auditory.calcIld - Calculate normalised interaural level difference +% iosr.auditory.chXcorr - Calculate cross-correlograms with a wide range of options +% iosr.auditory.chXcorr2 - Calculate cross-correlograms with a range of options +% chXcorr2_c.c +% chXcorr_c.c +% iosr.auditory.createWindow - Create a Hann or exp. window with specified onsets/offsets +% iosr.auditory.dupWeight - Calculate duplex weighting coefficients for ITD and ILD +% iosr.auditory.erbRate2hz - Convert ERB rate to Hz +% iosr.auditory.freqMulti - Calculate frequency coefficient for ITD-azimuth warping +% iosr.auditory.gammatoneFast - Produce an array of responses from gammatone filters via FFT +% iosr.auditory.hz2erbRate - Convert Hz to ERB rate +% iosr.auditory.iso226 - ISO 226:2003 Normal equal-loudness-level contours +% iosr.auditory.itd2azimuth - Convert ITD to azimuth +% iosr.auditory.lindemannInh - Signal pre-processing for Lindemann's cross-correlation +% iosr.auditory.loudWeight - Calculate loudness weighting coefficients +% iosr.auditory.makeErbCFs - Make a series of center frequencies equally spaced in ERB-rate +% iosr.auditory.meddisHairCell - Calculate Ray Meddis' hair cell model for a number of channels +% iosr.auditory.perceptualCentroid - Perceptual spectral centroid +% iosr.auditory.perceptualCentroid2 - Alternative perceptual spectral centroid +% iosr.auditory.xcorrLindemann - Cross-correlation based on Lindemann's precedence model +% xcorrLindemann_c.c +% +% +IOSR/+BSS +% iosr.bss.applyIdealMasks - Calculate and apply ideal masks via STFT +% iosr.bss.applyMask - Apply a time-frequency mask to an STFT +% iosr.bss.calcImr - Calculates the Ideal Mask Ratio (IMR) +% iosr.bss.calcSnr - Calculate the separation SNR +% iosr.bss.cfs2fcs - Calculate gammatone crossover frequencies +% iosr.bss.example - Determine STFT parameters +% iosr.bss.generateMixtures - Generate arrays of mixtures from targets and interferers +% iosr.bss.getFullMask - Convert frame rate mask to a sample-by-sample mask +% iosr.bss.idealMasks - Calculate ideal time-frequency masks from STFTs +% iosr.bss.mixture - Class of sound source separation mixture +% iosr.bss.resynthesise - Resynthesise a target from a time-frequency mask +% iosr.bss.source - Class of sound source separation source +% +% +IOSR/+DSP +% iosr.dsp.audio - Abstract superclass providing audio-related properties and methods +% iosr.dsp.autocorr - Perform autocorrelation via FFT +% iosr.dsp.convFft - Convolve two vectors using FFT multiplication +% iosr.dsp.istft - Calculate the Inverse Short-Time Fourier Transform +% iosr.dsp.lapwin - Laplace window +% iosr.dsp.localpeaks - Find local peaks and troughs in a vector +% iosr.dsp.ltas - Calculate the long-term average spectrum of a signal +% iosr.dsp.matchEQ - Match the LTAS of a signal to an arbitrary spectral magnitude +% iosr.dsp.rcoswin - Raised cosine window +% iosr.dsp.rms - Calculate the rms of a vector or matrix +% iosr.dsp.sincFilter - Apply a near-ideal low-pass or band-pass brickwall filter +% iosr.dsp.smoothSpectrum - Apply 1/N-octave smoothing to a frequency spectrum +% iosr.dsp.stft - Calculate the short-time Fourier transform of a signal +% iosr.dsp.vsmooth - Smooth a vector using mathematical functions +% +% +IOSR/+FIGURES +% iosr.figures.chMap - Create a monochrome-compatible colour map +% iosr.figures.cmrMap - Create a monochrome-compatible colour map +% iosr.figures.multiwaveplot - Stacked line plots from a matrix or vectors +% iosr.figures.subfigrid - Create axis positions for subfigures +% +% +IOSR/+GENERAL +% iosr.general.cell2csv - Output a cell array to a CSV file +% iosr.general.checkMexCompiled - Check if mex file is compiled for system +% iosr.general.getContents - Get the contents of a specified directory +% iosr.general.updateContents - Create a Contents.m file including subdirectories +% iosr.general.urn - Generate random number sequence without duplicates +% +% +IOSR/+STATISTICS +% iosr.statistics.boxPlot - Draw a box plot +% iosr.statistics.functionalBoxPlot - Draw a functional boxplot +% iosr.statistics.functionalPlot - Abstract superclass for functional plots +% iosr.statistics.functionalSpreadPlot - Draw a functional plot showing data spread +% iosr.statistics.getRmse - Calculate the root-mean-square error between input data +% iosr.statistics.laprnd - Pseudorandom numbers drawn from the Laplace distribution +% iosr.statistics.qqPlot - Quantile-quantile plot with patch option +% iosr.statistics.quantile - Quantiles of a sample via various methods +% iosr.statistics.statsPlot - An abstract superclass for classes that plot statistics +% iosr.statistics.tab2box - Prepare tabular data for boxPlot function +% iosr.statistics.trirnd - Pseudorandom numbers drawn from the triangular distribution +% +% +IOSR/+SVN +% iosr.svn.buildSvnProfile - Read data from files tagged with SVN keywords +% iosr.svn.headRev - Retrieve the head revision for specified files +% iosr.svn.readSvnKeyword - Read data from a file tagged with an SVN keyword +% +% This file was generated by updateContents.m on 31 May 2017 at 17:06:32. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/install.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/install.m new file mode 100644 index 0000000000000000000000000000000000000000..deacd6312ab065a2e39eee203b2869f509e94260 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/+iosr/install.m @@ -0,0 +1,52 @@ +function mypath = install +%INSTALL Set search paths, and download and install dependencies. +% +% IOSR.INSTALL downloads and installs the toolbox dependencies. The +% function also adds the required paths to the Matlab search path. +% +% MYPATH = IOSR.INSTALL returns the old Matlab search path MYPATH. + +% Copyright 2016 University of Surrey. + + %% download and install SOFA + + % install dir + currdir = cd; + cd([fileparts(which(mfilename('fullpath'))) filesep '..']); + directory = pwd; + sofa_folder = [directory filesep 'deps' filesep 'SOFA_API']; + + if ~(exist(sofa_folder,'dir') == 7) + % download and install + sofa_filename = 'sofa-api.zip'; + try % Sourceforge location changes from time to time + websave(sofa_filename,'http://vorboss.dl.sourceforge.net/project/sofacoustics/sofa-api-mo-1.0.2.zip'); + catch % Fall back to development release on GitHub + display('Warning: Failed to download SOFA v1.0.2 from Sourceforge, downloading development release...') + websave(sofa_filename,'https://github.com/sofacoustics/API_MO/archive/master.zip'); + end + unzip(sofa_filename,sofa_folder); + movefile([sofa_folder filesep 'API_MO' filesep '*'],[sofa_folder filesep]); + + % clean up + delete(sofa_filename) + rmdir([sofa_folder filesep 'doc' filesep],'s') + rmdir([sofa_folder filesep 'HRTFs' filesep],'s') + rmdir([sofa_folder filesep 'API_MO' filesep],'s') + else + display(strcat('Found existing SOFA directory: ', sofa_folder)) + end + + %% Add directories to path + + cd(directory); + mypath = addpath(directory,... + [directory filesep 'deps' filesep 'SOFA_API']); + + %% start SOFA + + SOFAstart(0); + + cd(currdir); % return to original directory + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/.gitignore b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e56622b5b9e28e99a03ee8a2bbef807cf8394a03 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/.gitignore @@ -0,0 +1,6 @@ +# compiled binary +*.mex* + +# temp files +*.m~ +*.c~ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/LICENSE b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..417e20b9e7e3077388f39b8340b3e8b3cc48d9dc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Institute of Sound Recording + +Permission is hereby granted,aining a free of charge, to any person obt copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/README.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/README.md new file mode 100644 index 0000000000000000000000000000000000000000..90c482ecc2288b591bd477223e1760c9724a75f4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/README.md @@ -0,0 +1,44 @@ +# IoSR Matlab Toolbox + +A general purpose Matlab toolbox containing functions and classes for: auditory modelling, signal processing, sound source separation, statistics, plotting, etc. See [Contents.m](https://github.com/IoSR-Surrey/Toolbox/blob/master/+iosr/Contents.m) for a full list of functions/classes. + +## Installation + +Basic installation only requires you to add the install directory to the Matlab search path. + +If you wish to perform certain audio / signal processing tasks (especially spatialisation), please navigate to the install directory and type + +``` +iosr.install +``` + +This will automatically download the toolbox's dependencies for these tasks, and add the necessary paths to your search path. + +## Usage + +Use these functions as: + +``` +iosr.<folderName>.<functionName>(<args>) +``` + +(Ignoring the '+' in the folder name.) Alternatively, use the `import` directive to add one or more namespaces, e.g.: + +``` +import iosr.auditory +import iosr.* +``` + +If using `import`, note that some function names may conflict with built-in Matlab function names (e.g. `quantile`). One method of resolving the conflict and shortening the function call is to create a handle to any functions with conflicting names, e.g. + +``` +qntl = @iosr.statistics.quantile; +``` + +Type + +``` +help iosr +``` + +for more information. \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/.gitignore b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..60e13b6534e1783a891f11edb50cec1cfe106572 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/.gitignore @@ -0,0 +1,29 @@ +# compiled convention files +/SOFAtoolbox/conventions/*.mat +/SOFAtoolbox/conventions/*.txt +# test files for demos +/SOFAtoolbox/demos/*.sofa +/SOFAtoolbox/demos/demo_FreeFieldHRTF/*.fig +/SOFAtoolbox/demos/demo_FreeFieldHRTF/*.png +/SOFAtoolbox/demos/LigetiHall_CubeletToSt450/ +/SOFAtoolbox/test/*.sofa +/SOFAtoolbox/test/*/*.wav +/SOFAtoolbox/test/LigetiHall_CubeletToSt450/ +/data/ARI/*/*.mat +/data/BTDEI/*/*/*/*/*/*.mat +/data/BTDEI/*/headphones_info.mat +/data/CIPIC/*/*.mat +/data/CIPIC/show_data/ +/data/CIPIC/CIPIC_hrtf_database/ +/data/FHK/*.mat +/data/IEM/*.wav +/data/IEM/*.pdf +/data/LISTEN/IRC_1002/ +/data/MIT KEMAR/full/*/*.wav +/data/Oldenburg/HRIR_database_mat/ +/data/SCUT/nearfield/ +/data/SOFA/sofatoolbox_test/*.sofa +/data/SOFA/database/*/*.sofa +/data/SOFA/headphones/*/*.sofa +/data/TU-Berlin KEMAR/*.mat +/SOFAtoolbox/helpers/*.m diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/README.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a9b1f711153bd443cad060444125bb484ecb0f27 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/README.md @@ -0,0 +1,64 @@ +SOFA - Spatially Oriented Format for Acoustics +============================================== + +SOFA is a file format for reading, saving, and describing spatially +oriented data of acoustic systems. + +Examples of data we consider are head-related transfer functions (HRTFs), +binaural room impulse responses (BRIRs), multichannel measurements such as done +with microphone arrays, or directionality data of loudspeakers. + +The format specification is the major focus of SOFA, but we also aim in providing +toolboxes for reading and writing the data in SOFA. For more information on the +format specifications and available data, see http://www.sofaconventions.org/. + +This project implements a reference toolbox for SOFA: The SOFA Toolbox. + +SOFA Toolbox 2.x implements SOFA versions 2.x. The SOFA Toolbox has been previously +known as the SOFA API_MO, which supported SOFA versions up to 1.x. + + +Downloads +========= + +Current releases of SOFA Toolbox can be found on its [old +home](http://sourceforge.net/projects/sofacoustics/files/?source=navbar). + +**Note:** +- The currently latest release is known as the SOFA API M/O version 1.1.3. +- The SOFA Toolbox 2.0 has never been released. +- The SOFA Toolbox 2.1 is currently under preparation. It will support SOFA 2.1 as known as AES69-2022. + + +Usage +===== + +## Matlab/Octave + +In order to use SOFA with Matlab or Octave add its `SOFAtoolbox` folder +to your search paths. After that you can play around with your acoustic measurements +as shown by the following example which uses a HRTF measurement. + +```matlab +%% put your information here: +hrtf = SOFAload('path/to_your/HRTF.sofa'); +soundInput = audioread('path/to_your/fancy_audio_file.wav'); + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(hrtf.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); +``` diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..dda2380db8f49f5f33175cf59d42dd0b3c23be07 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m @@ -0,0 +1,61 @@ +function Obj = SOFAaddVariable(Obj,Name,Dim,Value) +%SOFAaddVariable +% Obj = SOFAaddVariable(Obj,Name,Dim,Value) adds a user-defined variable +% to the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). DIM is a string +% describing the dimensions of the variable according to SOFA specifications. +% The content of NAME is stored in VALUE which must be of the size DIM. +% The used-defined variable NAME will be stored as Obj.NAME and its +% dimension will be stored as Obj.API.Dimensions.NAME. Note that user- +% defined variables can be saved in SOFA file and thus remain in the +% object when loaded from a SOFA file. +% +% Obj = SOFAaddVariable(Obj,Name,'PRIVATE',Value) adds a private variable +% to OBJ. The private variable NAME will be stored as Obj.PRIVATE.NAME. +% Note that the private variables will be not stored in SOFA files and +% arbitrary dimensions are allowed. +% +% Note that adding variables to Data is not supported and should not be used +% as it might be confusing having user-defined variables in a Data structure. +% Consider adding a variable at the global level instead, which would be more +% clear for others. + +% #Author: Piotr Majdak +% #Author: Piotr Majdak: dimension is added if not previously found. (9.8.2014) +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAaddVariable +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Dim=upper(Dim); +switch Dim + case 'PRIVATE' + Obj.PRIVATE.(Name)=Value; + otherwise + switch Name + case {'API','PRIVATE','GLOBAL'} + error('This variable name is reserved.'); + otherwise + if strncmp(Name,'Data.',length('Data.')) + % add variable to Data + Name=Name(length('Data.')+1:end); + Obj.Data.(Name)=Value; + Obj.API.Dimensions.Data.(Name)=Dim; + else + % add variable to root + Obj.(Name)=Value; + Obj.API.Dimensions.(Name)=Dim; + end + dims=SOFAdefinitions('dimensions'); + for ii=1:length(Dim) + if ~isfield(dims,Dim(ii)) + error('Dimension not supported.'); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m new file mode 100644 index 0000000000000000000000000000000000000000..4cd1e5367374580beb8290071fd3c9d3099dca5e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m @@ -0,0 +1,27 @@ +function output = SOFAappendText(Obj,attribute,new) +%SOFAappendText +% +% output = SOFAappendText(Obj,attribute,new) appends the new text to the +% attribute (as string) using the correct SOFA separators. If the attribute is empty +% or non-existing, the output will be the new text only. +% +% example: +% Obj.GLOBAL_Title = SOFAappendText(Obj, 'GLOBAL_Title', 'Append me to the title.'); + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAappendText +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~isfield(Obj,attribute), Obj.(attribute)=''; end +if isempty(Obj.(attribute)), + output=new; +else + output=[Obj.(attribute) SOFAdefinitions('EOL') new]; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m new file mode 100644 index 0000000000000000000000000000000000000000..7699a5664ee60e26c72ffdf90259d9f72db1aa2c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m @@ -0,0 +1,273 @@ +function [flags,keyvals,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun) +%SOFAARGHELPER Parse arguments for SOFA +% Usage: [flags,keyvals,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun); +% +% Input parameters: +% posdepnames : Names of the position dependant parameters. +% definput : Struct to define the allowed input +% arglist : Commandline of the calling function (varargin) +% callfun : Name of calling function (optional) +% +% Output parameters: +% flags : Struct with information about flags. +% keyvals : Struct with key / values. +% varargout : The position dependant pars. properly initialized +% +% [flags,keyvals,varargout]=SOFAarghelper(posdepnames,definput,arglist,callfun) assists in +% parsing input parameters for a function. Parameters come in +% four categories: +% +% Position dependant parameters. These must not be strings. These are +% the first parameters passed to a function, and they are really just a short way +% of specifying key/value pairs. See below. +% +% Flags. These are single string appearing after the position dependant +% parameters. +% +% Key/value pairs. The key is always a string followed by the value, which can be +% anything. +% +% Expansions. These appear as flags, that expand into a pre-defined list of parameters. +% This is a short-hand way of specifying standard sets of flags and key/value pairs. +% +% The parameters are parsed in order, so parameters appearing later in varargin will override +% previously set values. +% +% The following example for calling SOFAARGHELPER is taken from DGT: +% +% definput.keyvals.L=[]; +% definput.flags.phase={'freqinv','timeinv'}; +% [flags,kv]=SOFAarghelper({'L'},definput,varargin); +% +% The first line defines a key/value pair with the key 'L' having an initial value of `[]` +% (the empty matrix). +% +% The second line defines a group of flags by the name of phase. The +% group phase contains the flags `'freqinv'` and `'timeinv'`, which can +% both be specified on the command line by the user. The group-name +% phase is just for internal use, and does not appear to the user. The +% flag mentioned first in the list will be selected by default, and only +% one flag in a group can be selected at any time. A group can contain as +% many flags as desired. +% +% The third line is the actual call to SOFAARGHELPER which defines the +% output flags and `kv`. The input `{'L'}` indicates that the value of +% the parameter 'L' can also be given as the very first value in +% varargin. +% +% The output struct kv contains the key/value pairs, so the value associated to `'L'` is +% stored in kv.L. +% +% The output struct flags contains information about the flags choosen +% by the user. The value of flags.phase will be set to the selected flag +% in the group phase and additionally, the value of `flags.do_timeinv` +% will be 1 if 'timeinv' was selected and 0 otherwise, and similarly for +% 'freqinv'. This allows for easy checking of selected flags. +% + +% #Author: Peter L. Soendergaard, Copyright (C) 2005-2012 +% #Author: Piotr Majdak: Modified from the LTFAT 1.1.2 for SOFA by Piotr Majdak. +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. + +persistent SOFA_CONF; + +if isempty(SOFA_CONF) + SOFA_CONF.fundefs = struct; +end; + +if ischar(posdepnames) + % Special interface needed for ltfatsetdefaults and ltfatgetdefaults, + % activated when first argument is a string. + + % First input argument, posdepnames, is a string, one of the options + % in the "switch" section below + % Second input argument, definput, is a function name to get or set + % Third input argument, arglist , is a cell-array with options to set. + + switch(lower(posdepnames)) + case 'get' + if isfield(SOFA_CONF.fundefs,definput) + flags=SOFA_CONF.fundefs.(definput); + else + flags={}; + end; + case 'set' + SOFA_CONF.fundefs.(definput)=arglist; + case 'all' + flags=SOFA_CONF.fundefs; + case 'clearall' + SOFA_CONF.fundefs=struct; + end; + return +end; + +if nargin<4 + f=dbstack; + callfun=f(2).name; +end; + +nposdep=numel(posdepnames); + +% Resolve import specifications BEFORE adding our own specifications. +if isfield(definput,'import') + for imp = definput.import; + definput=feval(['arg_',imp{1}],definput); + end; +end; + +if isfield(definput,'flags') + defflags=definput.flags; +else + defflags=struct; +end; + +if isfield(definput,'keyvals') + defkeyvals=definput.keyvals; +else + defkeyvals=struct; +end; + +if isfield(definput,'groups') + groups=definput.groups; +else + groups=struct; +end; + +total_args = numel(arglist); + +% Determine the position of the first optional argument. +% If no optional argument is given, return nposdep+1 +first_str_pos = 1; +while first_str_pos<=total_args && ~ischar(arglist{first_str_pos}) + first_str_pos = first_str_pos +1; +end; + +% If more than nposdep arguments are given, the first additional one must +% be a string +if (first_str_pos>nposdep+1) + error('%s: Too many input arguments',upper(callfun)); +end; + +n_first_args=min(nposdep,first_str_pos-1); + +keyvals=defkeyvals; + +% Copy the given first arguments +for ii=1:n_first_args + keyvals.(posdepnames{ii})=arglist{ii}; +end; + +% Initialize the position independent parameters. +% and create reverse mapping of flag -> group +flagnames=fieldnames(defflags); +flags=struct; +% In order for flags to start with a number, it is necessary to add +% 'x_' before the flag when the flags are used a field names in +% flagreverse. Externally, flags are never used a field names in +% structs, so this is an internal problem in ltfatarghelper that is +% fixed this way. +flagsreverse=struct; +for ii=1:numel(flagnames) + name=flagnames{ii}; + flaggroup=defflags.(name); + flags.(name)=flaggroup{1}; + for jj=1:numel(flaggroup) + flagsreverse.(['x_', flaggroup{jj}])=name; + flags.(['do_',flaggroup{jj}])=0; + end; + flags.(['do_',flaggroup{1}])=1; +end; + +%Get the rest of the arguments +restlist = arglist(first_str_pos:end); + +%Check for default arguments +if isfield(SOFA_CONF.fundefs,callfun) + s=SOFA_CONF.fundefs.(callfun); + restlist=[s,restlist]; +end; + +% Check for import defaults +if isfield(definput,'importdefaults') + % Add the importdefaults before the user specified arguments. + restlist=[definput.importdefaults,restlist]; +end; + +while ~isempty(restlist) + argname=restlist{1}; + restlist=restlist(2:end); % pop + found=0; + + % Is this name a flag? If so, set it + if isfield(flagsreverse,['x_',argname]) + % Unset all other flags in this group + flaggroup=defflags.(flagsreverse.(['x_',argname])); + for jj=1:numel(flaggroup) + flags.(['do_',flaggroup{jj}])=0; + end; + + flags.(flagsreverse.(['x_',argname]))=argname; + flags.(['do_',argname])=1; + found=1; + end; + + % Is this name the key of a key/value pair? If so, set the value. + if isfield(defkeyvals,argname) + keyvals.(argname)=restlist{1}; + restlist=restlist(2:end); + found=1; + end; + + % Is this name a group definition? If so, put the group in front of the parameters + if isfield(groups,argname) + s=groups.(argname); + restlist=[s,restlist]; + found=1; + end; + + % Is the name == 'argimport' + if strcmp('argimport',argname) + fieldnames_flags= fieldnames(restlist{1}); + fieldnames_kvs = fieldnames(restlist{2}); + for ii=1:numel(fieldnames_flags) + importname=fieldnames_flags{ii}; + flags.(importname)=restlist{1}.(importname); + end; + for ii=1:numel(fieldnames_kvs) + importname=fieldnames_kvs{ii}; + keyvals.(importname)=restlist{2}.(importname); + end; + restlist=restlist(3:end); + found=1; + end; + + if found==0 + if ischar(argname) + error('%s: Unknown parameter: %s',upper(callfun),argname); + else + error('%s: Parameter is not a string, it is of class %s',upper(callfun),class(argname)); + end; + end; + + %ii=ii+1; +end; + +% Fill varargout + +varargout=cell(1,nposdep); +for ii=1:nposdep + varargout(ii)={keyvals.(posdepnames{ii})}; +end; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m new file mode 100644 index 0000000000000000000000000000000000000000..bb8c5816c4caf6be538d13a9b96d809a1323411f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m @@ -0,0 +1,76 @@ +function ApparentPositionVector = SOFAcalculateAPV(Obj) +%SOFAcalculateAPV +% ApparentPositionVector = SOFAcalculateAPV(Obj) calculates the apparent position vector +% (ApparentPositionVector) which represents the position of the source relative to the +% listener's position and view. ApparentPositionVector is in the format [azi ele radius] +% with units [deg deg m]. +% Note that ListenerUp is not considered and the ApparentPositionVector can be considered as +% the HRTF direction usually used in HRTF databases + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAcalculateAPV +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% === Apparent azimuth === +% Apparent azimuth is the relative direction of the sound source in the +% horizontal plane from the listener viewpoint +% +% Get head orientation of the listener and source position in spherical +% coordinates +HeadOrientation = SOFAconvertCoordinates( ... + Obj.ListenerView,Obj.ListenerView_Type,'spherical'); +SourcePosition = SOFAconvertCoordinates( ... + Obj.SourcePosition,Obj.SourcePosition_Type,'spherical'); +% Calculate the relative azimuth angle between them +APVazimuth = correctAzimuth(bsxfun( ... + @minus,SourcePosition(:,1),HeadOrientation(:,1))); + +% === Apparent elevation === +% Apparent elevation is the relative direction of the sound source in the median +% plane from the listener viewpoint +APVelevation = correctElevation(bsxfun( ... + @minus,SourcePosition(:,2),HeadOrientation(:,2))); + +% === Apparent distance === +% Apparent distance is the relative distance between the sound source and the +% listener +% +% Get listener positon in spherical coordinates +ListenerPosition = SOFAconvertCoordinates( ... + Obj.ListenerPosition,Obj.ListenerPosition_Type,'spherical'); +% Relative distance +APVdistance = bsxfun(@minus,SourcePosition(:,3),ListenerPosition(:,3)); + +% Combine to matrix +ApparentPositionVector = [ ... + APVazimuth, ... + APVelevation, ... + APVdistance, ... +]; + +end + +function phi = correctAzimuth(phi) + % Ensure -360 <= phi <= 360 + phi = rem(phi,360); + % Ensure -180 <= phi < 180 + phi(phi<-180) = phi(phi<-180) + 360; + phi(phi>=180) = phi(phi>=180) - 360; +end + +% TODO: check what convetion we are using for delta! +function delta = correctElevation(delta) + % Ensure -180 <= delta <= 180 + delta = correctAzimuth(delta); + % Ensure -90 <= delta <= 90 + delta(delta<-90) = -delta(delta<-90) - 180; + delta(delta>90) = -delta(delta>90) + 180; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m new file mode 100644 index 0000000000000000000000000000000000000000..73d74f7f70139b0ebf4cdd2a7f03da5ea5c59f14 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m @@ -0,0 +1,389 @@ +function [toa_diff,toa,IACC,Obj] = SOFAcalculateITD(Obj,varargin) +% SOFAcalculateITD: Estimate ITD from a binaural signal +% Usage: [itd,toa,IACC,Obj] = SOFAcalculateITD(data,mode,threshlvl,lowpass,butterpoly,upper_cutfreq) +% +% Input parameters: +% +% data: SOFA object or IR matrix with dimensions: +% emitter x receiver x time +% +% fs: sampling rate, used only if data provided as matrix +% +% mode: (optional) Select one estimation methods +% (Threshold (default),Cen_e2,MaxIACCr, MaxIACCe, +% CenIACCr,CenIACCe, CenIACC2e, PhminXcor,IRGD) +% +% lowpass: (optional) Bandwidth considered. lp for lowpass (default), bb for broadband +% +% peak: (optional) Method to find the max, used in Threshold mode only. +% hp for max (default), fb for findpeak +% +% threshlvl: (optional) Set threshold level for Threshold mode in dB. +% Default is -10 dB. +% +% butterpoly: (optional) Select the order of the polynom +% applied in the butterworth filter. ( 2 =< i =< 10 ) +% Default is 10. +% +% upper_cutfreq: (optional) Set frequency of lowpass cutoff in Hz. +% Default is 3000 Hz. +% +% lower_cutfreq: (optional) Set frequency of highpass cutoff in Hz, +% only used in IRGD mode. Default is 1000 Hz. +% +% debug : output debug information about calculations. +% +% +% Output parameters: +% +% itd: interaural time difference in seconds +% toa: detected activation onsets for left and right channels +% IACC: interaural cross-correlation coefficient +% Available on when xcorr is used (modes: MaxIACCr, MaxIACCe, +% CenIACCr,CenIACCe, CenIACC2e) +% Obj: Input SOFA object with Obj.Data.Delay added +% +% +% Purpose: +% Estimates the ITD based on biaural impulse responses. +% Several different estimaton methods can be chosen. +% MaxIAACe is recommended. +% +% +% Examples: +% --------- +% +% Obj = SOFAload(fullfile(SOFAdbPath,'baumgartner2017','hrtf b_nh15.sofa')); +% toa_diff = SOFAcalculateITD(Obj,'MaxIACCe','lp','upper_cutfreq',3000) +% +% With these settings the estimator uses the MaxIAAce method and applies +% a lowpass with a cut off frequency of 3 kHz. +% +% The output array is structured as the SOFA Data.IR +% If you would like to select for example only data on the horizontal +% plane you could: +% +% plane_idx = find( Obj.SourcePosition(:,2) == 0 ); +% plane_angle = Obj.SourcePosition(plane_idx,1); +% +% Url: https://amtoolbox.org/amt-1.2.0/doc/common/itdestimator_code.php + +% #Author: AMToolbox, Laurin Steidle, Piotr Majdak, Clara Hollomey, and the AMT team +% #Author: Robert Baumgartner: data matrix option +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% #Author: Michael Mihocic: adaption for SOFA Toolbox 2.0 +% #Author: Michael Mihocic: updated to version 1.2.0 of function itdestimator in Auditory Modeling Toolbox (AMT) (01.08.2022) +% +% This file is part of the SOFA Toolbox 2.0, +% basing on the function itdestimator in Auditory Modeling Toolbox (AMT) version 1.2.0 +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + + + +% ---------------------- SOFAarghelper ------------------------------- +% default parameters (adapted from arg_itdestimator) +definput.keyvals.debug = 0; +definput.flags.mode = {'Threshold','Cen_e2','MaxIACCr', 'MaxIACCe', 'CenIACCr', 'CenIACCe', 'CenIACC2e', 'PhminXcor','IRGD'}; +definput.flags.lp = {'lp','bb'}; +definput.flags.peak = {'hp','fp'}; +definput.flags.toaguess = {'noguess','guesstoa'}; +definput.keyvals.threshlvl = -10; +definput.keyvals.butterpoly = 10; +definput.keyvals.upper_cutfreq = 3000; +definput.keyvals.lower_cutfreq = 1000; +definput.keyvals.avgtoa = 45; +definput.keyvals.fs = []; +definput.keyvals.thr = 20; % dB +definput.keyvals.upsample = 16; % dB +definput.flags.units = {'time', 'samples'}; + +[flags,kv]=SOFAarghelper({},definput,varargin); + +% ---------------------- renaming input parameter --------------------- + +if isstruct(Obj) + pos = Obj.API.M; + ear = Obj.API.R; + Ns = Obj.API.N; + IR = Obj.Data.IR; + fs = Obj.Data.SamplingRate; +else + pos = size(Obj,1); + ear = size(Obj,2); + Ns = size(Obj,3); + IR = Obj; + if isempty(kv.fs) + error('RB: No sampling rate (fs) provided.') + end + fs = kv.fs; +end + +% ---------------------- initialising variables ----------------------- + +toa = zeros(pos,ear); +toa_diff = zeros(pos,1); +IACC = zeros(pos,1); +% delay = zeros(length(Obj.SourcePosition), 2); + +if kv.debug == 1; disp('SOFAcalculateITD:'); end + +% ---------------------- Applying low-pass ---------------------------- + +if flags.do_lp + if kv.debug == 1 + disp(' Applying Butterworth low pass ') + disp(strcat(' Polynomial order of Butterworth filter: ',num2str(kv.butterpoly))) + disp(strcat(' Cut-off frequency is: ',num2str(kv.upper_cutfreq),' Hz')) + end + % if isoctave; pkg load signal; end + if exist('OCTAVE_VERSION','builtin') ~= 0; pkg load signal; end + cut_off_freq_norm = kv.upper_cutfreq/(fs/2); + + [lp_a,lp_b] = butter(kv.butterpoly,cut_off_freq_norm); + f_ir = zeros(pos,ear,Ns); + for ii=1:pos + for jj=1:ear + sir = squeeze( IR(ii,jj,:) ); + f_sir = filter(lp_a,lp_b,sir); + f_ir(ii,jj,:) = f_sir; + end + end + +else + if kv.debug == 1; disp(' No low pass filter is applied'); end + f_ir = IR; +end + +% ---------------------- estimating itd ------------------------------- +% --------------------------------------------------------------------- + +% ---------------------- Threshold ------------------------------------ +switch(flags.mode) + case 'Threshold' + if kv.debug == 1 + disp(' Threshold mode') + disp(strcat(' Threshold level is: ',num2str(kv.threshlvl),'dB')) + end + + if flags.do_fp + for ii=1:pos + for jj=1:ear + indB = 0.5*mag2db(squeeze(f_ir(ii,jj,:)).^2); + [~,B] = findpeaks(indB); + th_value = indB(B(1)) + kv.threshlvl; + toa(ii,jj) = find(indB>th_value,1); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + else + for ii=1:pos + for jj=1:ear + indB = 0.5*mag2db(squeeze(f_ir(ii,jj,:)).^2); + th_value = max(indB) + kv.threshlvl; + idx=find(indB>th_value,1); + if isempty(idx), idx=NaN; end + toa(ii,jj) = idx; + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + end + + +% ---------------------- Cross-Correlation ---------------------------- + case 'Cen_e2' + if kv.debug == 1; disp(' Cen-e2 mode'); end + for ii=1:pos + for jj = 1:ear + e_sir_sq = abs(hilbert(squeeze(f_ir(ii,jj,:))).^2); + toa(ii,jj) = centroid(transpose(1:Ns),e_sir_sq); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + + case 'MaxIACCr' + if kv.debug == 1; disp(' MaxIACCr mode'); end + for ii=1:pos + cc = xcorr(squeeze(f_ir(ii,1,:)),squeeze(f_ir(ii,2,:))); + [IACC(ii),idx_lag] = max(abs(cc)); + toa_diff(ii) = idx_lag - Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + case 'MaxIACCe' + if kv.debug == 1; disp(' MaxIACCe mode'); end + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2); + [IACC(ii),idx_lag] = max(abs(cc)); + toa_diff(ii) = idx_lag - Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACCr' + if kv.debug == 1; disp(' CenIACCr mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + cc = xcorr(squeeze(f_ir(ii,1,:)),squeeze(f_ir(ii,2,:))); + pos_cc = abs(cc); + IACC(ii) = max(pos_cc); + toa_diff(ii) = centroid(x,pos_cc)-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACCe' + if kv.debug == 1; disp(' CenIACCe mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2); + IACC(ii) = max(abs(cc)); + toa_diff(ii) = centroid(x,abs(cc))-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACC2e' + if kv.debug == 1; disp(' CenIACC2e mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2).^2; + IACC(ii) = max(abs(cc)); + toa_diff(ii) = centroid(x,abs(cc))-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'PhminXcor' + if kv.debug == 1; disp(' PhminXcor mode'); end + ir_min=ARI_MinimalPhase(Obj); + for ii=1:pos + for jj=1:ear + cc = xcorr(squeeze(IR(ii,jj,:)),squeeze(ir_min(ii,jj,:))); + [~,toa(ii,jj)] = max(abs(cc)); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + +% ---------------------- Groupdelay ----------------------------------- + case 'IRGD' + if kv.debug == 1; disp(' IRGD mode'); end + for ii = 1:pos + for jj = 1:ear + f_sir = squeeze( f_ir(ii,jj,:) ); + [gd,w] = grpdelay(transpose(double(f_sir)),1,Ns,fs); + toa(ii,jj)=mean(gd(find(w>kv.lower_cutfreq): ... + find(w>kv.upper_cutfreq))); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end +end +toa_diff = toa_diff/fs; +toa = toa/fs; + +% Calculate Delay, add to Obj +for k = 1:size(IR, 1) + % Get onset + OnSetL = IR_start(IR(k,1,:), kv.thr); % L + OnSetR = IR_start(IR(k,2,:), kv.thr); % R + % Onset difference + delay(k,:) = [OnSetL, OnSetR]; +end + +Obj = SOFAaddVariable(Obj,'Data.Delay','MR',delay); + + + +% ------------------------------------------------------------------------- +% ---------------------- Functions ---------------------------------------- +% ------------------------------------------------------------------------- + + +% ---------------------- Centroid ----------------------------------------- +function idx_cent = centroid(x,y) +idx_cent = sum(x.*y)/sum(y); + +% ---------------------- guess toa ---------------------------------------- +function toa = guesstoa(toa_diff,toa, avgtoa) +toa(:,1) = toa(:,1) + avgtoa + toa_diff/2; +toa(:,2) = toa(:,2) + avgtoa - toa_diff/2; + +% ---------------------- Create minimal phase ----------------------------- +% as used in ziegelwanger2014 +function hMmin=ARI_MinimalPhase(Obj) +hM=Obj.Data.IR; +hMmin=hM; + +for jj=1:Obj.API.R + for ii=1:Obj.API.M + h=squeeze(hM(ii,jj,:)); + + amp1=abs(fft(h)); + amp2=amp1; + + an2u=-imag(hilbert(log(amp1))); + an2u=an2u(1:floor(length(h)/2)+1); + + an3u=[an2u; -flipud(an2u(2:end+mod(length(h),2)-1))]; + an3=an3u-round(an3u/2/pi)*2*pi; + + amp2=amp2(1:floor(length(h)/2)+1); + amp3=[amp2; flipud(amp2(2:end+mod(length(h),2)-1))]; + + h2=real(ifft(amp3.*exp(1i*an3))); + hMmin(ii,jj,:)=h2(1:Obj.API.N); + end +end + +% -------------------------- sampleStart ---------------------------------- +function sampleStart = IR_start(IR,threshold) +% 20210207 - Davi Carvalho, adapted from ita_start_IR.m from https://git.rwth-aachen.de/ita/toolbox/-/blob/master/kernel/DSP/ita_start_IR.m +threshold = -abs(threshold); +IR_square = IR.^2; +% Max value on IR +[pk_val, idx_max] = max(IR_square(:)); +abs_dat = 10.*log10(IR_square(1:idx_max)) - 10.*log10(pk_val); + +lastBelowThreshold = find(abs_dat < threshold,1,'last'); +if ~isempty(lastBelowThreshold) + sampleStart = lastBelowThreshold; +else + sampleStart = 1; +end +% Check if oscillations exist before the last value below threshold +% If so, these are part of the RIR and need to be considered. +idx6dBaboveThreshold = find(abs_dat(1:sampleStart) > threshold + 6); +if ~isempty(idx6dBaboveThreshold) + tmp = find(abs_dat(1:idx6dBaboveThreshold(1)) < threshold, 1 ,'last'); + if isempty(tmp) % without this if, the function would generate an error, if the oscillation persists until the first sample + sampleStart = 1; + else + sampleStart = tmp; + end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m new file mode 100644 index 0000000000000000000000000000000000000000..6fee405fec7c7dafdcdbbd9a65b4367f3fed38de --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m @@ -0,0 +1,111 @@ +function Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax) +% Low frequency extention +% +% function Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax) +% +% Description: +% This function extrapolates low frequency content of +% SOFA SimpleFreeFieldHRIR objects by considering a +% linear behavior to the low frequency content + +% Usage: Obj = SOFAcalculateLFE(Obj, fmin, fmax) +% +% Input parameters: +% Obj: SOFA object with SimpleFreeFieldHRIR convention. +% fmin: Minimal frequency to be calculated (default: 15Hz) +% fmax: Reference frequency value to be extended until fmin +% (default: 500Hz) +% +% Output arguments: +% Obj: SOFA object with SimpleFreeFieldHRIR convention. + + +% #Author: Davi R. Carvalho, UFSM - Acoustical Engineering (07.04.2021) +% #Author: Michael Mihocic: adapted for SOFA 2.0 release; header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcalculateLFE +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% parse inputs +if nargin < 3 + fmax = 500; % max linear frequency +end +if nargin < 2 + fmin = 15; % minimum freq +end + +%% Preprocess +fs = Obj.Data.SamplingRate; +IR = shiftdim(Obj.Data.IR, 2); +N = size(IR, 1); +freq_vec = (0:N/2-1)*fs/N; + +% Check if defined fmax data exists in raw hrir +if length(find(fmax > freq_vec)) == 1 + fmax = freq_vec(3); +end + + +% Minimum length necessary to contain fmin +N_ext = ceil(fs/fmin); +if N_ext <= N + N_ext = N; + freq_vec_ext = freq_vec; +else + freq_vec_ext = (0:N_ext/2-1)*fs/N_ext; +end +f500Hz = dsearchn(freq_vec_ext.', fmax); % idx at defined linear part of HRTFs + +[~, ~, ~, Obj] = SOFAcalculateITD(Obj, 'samples', 'debug', 1); +% [~, ObjD] = SOFAcalculateITDdavi(Obj, 'samples'); + +%% extrap low frequency +ir_interp = zeros(size(IR, 2), size(IR, 3), N_ext); +for k = 1:size(IR, 2) + for l = 1:size(IR, 3) + time = [IR(:,k,l); zeros(ceil(N_ext - N), 1)]; + mag = mag2db(abs(fft(time))); + mag_interp = mag; + + % interp + x = [1, f500Hz]; + xq = [1:f500Hz]; + y_mag = [mag(f500Hz); mag(f500Hz)]; + if exist('OCTAVE_VERSION','builtin') + mag_interp(1:f500Hz) = interp1(x, y_mag, xq); + else + mag_interp(1:f500Hz) = interp1(x, y_mag, xq, 'makima'); + end + + mag_interp = 10.^(mag_interp./20); + H = mag_interp(1:round(N_ext/2)); + + % back to time domain + ir_interp(k,l,:) = circshift(real(ifft(get_min_phase(abs(H)))), Obj.Data.Delay(k,l)); + end +end + + +%% OUTPUT +Obj_lfe = Obj; +% ir_interp = ir_interp./max(abs(ir_interp(:))) .* max(abs(IR(:))); +Obj_lfe.Data.IR = ir_interp; +end + + +function Hmin = get_min_phase(H, varargin) +% Calculate minimum-phase spectrum from magnitude via the Hilbert Transform +%% Preprocess +H = [H; flip(H)]; % back to double sided spectrum + +%% Get minimum_phase +phi_min = imag(hilbert(-(log(abs(H)+eps)))); % eps makes avoids log(0) = -inf +% Filtro inverso complexo (cria fase) +Hmin = abs(H).*exp(1i*(phi_min)); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m new file mode 100644 index 0000000000000000000000000000000000000000..cbf03103a4ae032e8078a9916fddb18a94f863a8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m @@ -0,0 +1,30 @@ +function newfn=SOFAcheckFilename(fn) +%SOFACHECKFILENAME +% newFN = SOFAcheckFilename(FN) checks the filename FN replaces certain characters + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcheckFilename +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% filename = string? +if ~ischar(fn) + error('Filename must be a string.'); +end +if strcmp(fn(1:7),'http://') + newfn=fn; % remote file +else + fn=strrep(fn,'/',filesep); + fn=strrep(fn,'\',filesep); + if length(fn)>4 + if strcmpi(fn(1:4),['db:' filesep]), fn=[SOFAdbPath fn(5:end)]; end + end + newfn=fn; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..c055c62533f41e7a6950b9d4de2b2d4cddf64f08 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m @@ -0,0 +1,93 @@ +function [Obj, log] = SOFAcompact(Obj) +%SOFAcompact +% Obj = SOFAcompact(Obj) +% compacts the unique value to singleton dimensions +% of variables where possible. +% Current limitation: Variables with 3 dimensions will be only compacted +% when the third dimension is the compressible one. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcompact +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence") +% You may not use this work except in compliance with the Licence. +% You may obtain a copy of the Licence at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the Licence for the specific language governing permissions and limitations under the Licence. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); +dims=SOFAdefinitions('dimensions'); + +%% compact w/o data +X=rmfield(Obj,{'Data','API'}); +Xf=fieldnames(X); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % get all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.(Xf{ii}),'rows'); else n=unique(Obj.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.(Xf{ii})=n; else Obj.(Xf{ii})=n'; end; % compressed! + case 3 + d=cell2mat(strfind(dims,'I')); + switch d + case 3 + y=unique(reshape(Obj.(Xf{ii}),[],size(Obj.(Xf{ii}),d))','rows'); + if size(y,1)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=reshape(y',size(Obj.(Xf{ii}),1),size(Obj.(Xf{ii}),2)); + otherwise + warning('SOFA:compact',[Xf{ii} ' not compressed (currently limited)']); + end + end +end + +%% Compact the data +Xf=fieldnames(Obj.Data); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.Data.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.Data.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.Data.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.Data.(Xf{ii}),'rows'); else n=unique(Obj.Data.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.Data.(Xf{ii})=n; else Obj.Data.(Xf{ii})=n'; end; % compressed! + case 3 + % missing + warning('SOFA:compact',['Data.' Xf{ii} ' not compressed (functionality limited)']); + end +end + +%% clean up +Obj=SOFAupdateDimensions(Obj); +if length(log)>1, log=log(2:end); else log={}; end; + +function vec=getdim(Obj,str) +vec=NaN(1,length(str)); +for ii=1:length(str) + vec(ii)=Obj.(upper(str(ii))); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m new file mode 100644 index 0000000000000000000000000000000000000000..f703e3f1318172591967cb13856444be985abe96 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m @@ -0,0 +1,58 @@ +function [tf,reason,where] = SOFAcompare(Obj1, Obj2, varargin) +%SOFAcompare +% TF = SOFAcompare(A, B) compares A and B and +% returns logical 1 (true) if they are identical. +% +% [TF,REASON,WHERE] = SOFAcompare(A, B) provides the REASON +% and shows WHERE the difference arose. +% +% ... = SOFAcompare(A, B, 'ignoreDate') ignores the global attributes +% DateCreated and DateModified. +% +% +% Limited functionality!!! Only attributes are compared now. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAcompare +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.flags.type={'all','ignoreDate'}; +[flags,~]=SOFAarghelper({},definput,varargin); + + +tf=1; +reason=''; +where=''; + +% % check if the size is equal +% o1=whos('Obj1'); +% o2=whos('Obj2'); +% if o1.bytes ~= o2.bytes, tf=0; reason='Different size'; return; end + + % get the field names +Xf=fieldnames(Obj1); + + % ignore DateCreated and DateModified? +if flags.do_ignoreDate + Xf=fieldnames(rmfield(Obj1,{'GLOBAL_DateCreated','GLOBAL_DateModified'})); +end + + % check if we have the same fields in Obj2 as in Obj1 +for ii=1:length(Xf) + if ~isfield(Obj2,Xf{ii}), tf=0; reason='Field missing in B'; where=Xf{ii}; return; end +end + + % check if we have the same content of attributes in Obj2 as in Obj1 +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), continue; end + if ~strcmp(Obj1.(Xf{ii}),Obj2.(Xf{ii})), tf=0; reason='Field not equal'; where=Xf{ii}; return; end +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..d1919ecf97105fd41955d27d2bd6238551f4e422 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m @@ -0,0 +1,209 @@ +function [dispOutput] = SOFAcompileConventions(conventions) +%SOFAcompileConventions +% +% [dispOutput] = SOFAcompileConventions(sofaconventions) compiles the specified +% SOFA conventions. For every convention, a CSV file must exist that +% will be compiled to a .mat file and used later by SOFAgetConventions(). +% +% The CSV file must be in the directory conventions and can contain +% files for multiple versions of the same conventions. For each version, +% SOFAcompileConventions generates 3 files, one for each flag (r, m, and all) +% +% Before compiling, SOFAcompileConventions checks if the modification +% date of the .mat files is older than that of the .csv file. Compiling +% is not performed if all .mat files are newer than the .csv file. This +% behaviour is required for operation in a read-only directory. +% +% SOFAcompileConventions ignores all files beginning with '_' (underscore). +% +% Output variable dispOutput contains a string with all compiled +% conventions information. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (20.10.2021) +% #Author: Michael Mihocic: display information changed to output variable (11.11.2021) +% +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +baseFolder = fileparts(which('SOFAstart')); +dispOutput=''; + +if nargin<1 + conventionFiles = dir(fullfile(baseFolder,'conventions','*.csv')); + conventions={}; + for file = conventionFiles' + [~,name,~] = fileparts(file.name); + if name(1)=='_', continue; end + % Check if mat files exist for every convention flag (r,m,a) + flagsCounter = 0; + for flag = 'rma' + flagFile = dir(fullfile(baseFolder,'conventions', ... + strcat(name,'_',flag,'_*.mat'))); + if ~isempty(flagFile) && flagFile(1).datenum>file.datenum + flagsCounter = flagsCounter+1; + end + end + % If not all three files are up to request conventions compilation + if flagsCounter~=3 + conventions{end+1} = name; + end + end +elseif ~iscell(conventions) + conventions={conventions}; +end + + +%% ----- Convert convention csv files into mat files ----- +for convention = conventions + % Read convention description from csv file + fid = fopen(fullfile(baseFolder,'conventions', ... + strcat(convention{:},'.csv'))); + if exist('OCTAVE_VERSION','builtin') + % We're in Octave where textscan works differently since ver. 4.2 + C_lines = textscan(fid,'%s','Delimiter','\n','Headerlines',1); + C_line = C_lines{1}{1}; + C_elems = cell(length(C_lines{1}),1); + C_maxcols = 2; + for line_nr = 1:length(C_lines{1}) + C_line = C_lines{1}{line_nr}; + C_elems{line_nr} = strsplit(C_line, '\t', 'collapsedelimiters', false); + C_maxcols = max(C_maxcols, length(C_elems{line_nr})); + end + % C = cell(1,length(C_elems{1})); + C = cell(1,C_maxcols); + for col_nr = 1:C_maxcols + % for col_nr = 1:length(C_elems{1}) + C{col_nr} = cell(length(C_lines{1}),1); + end + for line_nr = 1:length(C_lines{1}) + for col_nr = 1:length(C_elems{line_nr}) + % for col_nr = 1:length(C_elems{1}) + C{col_nr}{line_nr} = C_elems{line_nr}{col_nr}; + end + end + else + x=char(fread(fid)); + xr=strrep(x',char([9 13 10]),char([9 32 32 13 10])); + C = textscan(xr,'%s%s%s%s%s%s','Delimiter','\t','Headerlines',1,'WhiteSpace',''); + end + fclose(fid); + + % Convert to mat files for r,m,a cases + for flag = 'rma' + % Convert to SOFA object + Obj = compileConvention(C,flag); + % Write to mat file +% if strcmp(Obj.GLOBAL_SOFAConventions,convention{:}) + if strcmp(flag,'r') % && dispOutput==1 % Display message only the very first time +% disp(['Compiling ',convention{:},'.csv: ', ... +% Obj.GLOBAL_SOFAConventions, ' ', ... +% Obj.GLOBAL_SOFAConventionsVersion]); + if ~strcmp(dispOutput,''); dispOutput = [dispOutput 10]; end + dispOutput = [dispOutput 'Compiling ',convention{:},'.csv: ', Obj.GLOBAL_SOFAConventions, ' ', Obj.GLOBAL_SOFAConventionsVersion]; + end + save(fullfile(baseFolder,'conventions', ... + strcat(Obj.GLOBAL_SOFAConventions,'_',flag,'_', Obj.GLOBAL_SOFAConventionsVersion,'.mat')), ... + 'Obj','-v7'); +% else +% warning([convention{:} '.csv: file name not convention name (' Obj.GLOBAL_SOFAConventions]); +% end + end +end +end % of main function + + +%% ----- Subroutines ----------------------------------------------------- +function Obj = compileConvention(convention,flag) + % Compile convention mat structure for the specified flag + % + % The csv files provide the following columns (corresponding cell numbers in + % brackets) + % Name {1}, Default {2}, Flags {3}, Dimensions {4}, Type {5}, Comment {6} + convName = convention{1}; + convDefault = convention{2}; + convFlags = convention{3}; + convDimensions = convention{4}; + convType = convention{5}; + convComment = convention{6}; + + % Create object structure + for ii=1:length(convName) + % Append 'a' to Flags entry as it only contains 'm' or 'r' in the csv file + convFlags{ii} = strcat(convFlags{ii},'a'); + if ~isempty(regexp(convFlags{ii},flag, 'once')) + var = regexprep(convName{ii},':','_'); + switch lower(convType{ii}) + case 'double' + % Convert default to double + convDefault{ii} = str2num(convDefault{ii}); + case 'string' + eval(['convDefault{ii}=' convDefault{ii} ';']); + end + if isempty(strfind(var,'Data.')) + Obj.(var) = convDefault{ii}; + if isempty(strfind(var,'_')) % && ~sum(strcmp(var,dims)) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quotations and insert line breaks + Obj.API.Dimensions.(var)=eval(['{''' y '''}']); + end + else + Obj.Data.(var(6:end)) = convDefault{ii}; + if isempty(strfind(var(6:end),'_')) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quatations and insert line breaks + Obj.API.Dimensions.Data.(var(6:end))=eval(['{''' y '''}']); + end + end + end + end + + + % ----- Overwrite some special fields ----- + if isfield(Obj,'GLOBAL_APIVersion') + Obj.GLOBAL_APIVersion = SOFAgetVersion; + end + if isfield(Obj,'GLOBAL_APIName') + Obj.GLOBAL_APIName = 'ARI Matlab/Octave API'; + end + + % ----- Create dimension size variables - if not read-only ----- + if strcmp(flag,'r') + return; + else + % Fix dimension sizes (why we have to fix them?) + Obj.API.I = 1; + Obj.API.C = 3; + % Variable-dependent dimension sizes + dims = 'renm'; + % Check all metadata variables + fields =fieldnames(rmfield(Obj.API.Dimensions,'Data')); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(fields{jj}),dim(1)); + break; + end + end + end + % Check all data variables + fields = fieldnames(Obj.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.Data.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fields{jj}),dim(1)); + break; + end + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..577719ebb84f7a8e5f299e8c3de1404d1a07562d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m @@ -0,0 +1,461 @@ +function Obj=SOFAconvertConventions(Obj,varargin) +% Obj = SOFAconvertConventions(Obj) converts a SOFA object to SimpleFreeFieldHRIR +% +% Supported conventions: +% SimpleFreeFieldSOS +% SimpleFreeFieldTF +% SimpleFreeFieldHRTF +% FreeFieldHRTF +% some special cases of GeneralTF, GeneralTF-E. +% +% When using optional input values, they are transferred to and must be supported by SOFAarghelper function: +% Obj=SOFAconvertConventions(Obj,varargin) +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% get convention to be converted +if ~isempty(varargin) + definput.flags.convention=SOFAgetConventions(); + definput.flags.convention=strrep(definput.flags.convention,'-','_'); + + if contains(varargin,'-') + varargin=strrep(varargin,'-','_'); + end + [flags,~]=SOFAarghelper({},definput,varargin); + + newConvention = flags.convention; + if contains(newConvention,'_') + newConvention=strrep(newConvention,'_','-'); + end + % check if given convention is available + if isempty( SOFAgetConventions(newConvention)) + error([newConvention, ' not a valid convention.']) + end +else + newConvention = 'SimpleFreeFieldHRIR'; +end +oldConvention = Obj.GLOBAL_SOFAConventions; +%% no conversion needed if convention is the same +if(strcmp(oldConvention,newConvention)) +% warning(['No conversion done, as Obj already conforms to ', newConvention,'.']) + return +end + +%% convert Object +newObj = SOFAgetConventions(newConvention); +oldObj = SOFAgetConventions(oldConvention); + +Obj.GLOBAL_SOFAConventions=newObj.GLOBAL_SOFAConventions; +Obj.GLOBAL_SOFAConventionsVersion=newObj.GLOBAL_SOFAConventionsVersion; +Obj.GLOBAL_Conventions = newObj.GLOBAL_Conventions; +% convert Data +try + switch Obj.GLOBAL_DataType + case 'SOS' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + Obj.Data.IR(ii,jj,:)=sosfilt(reshape(squeeze(Obj.Data.SOS(ii,jj,:)),6,[])',impulse); + end + end + Obj.Data=rmfield(Obj.Data,'SOS'); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Data.SOS = Obj.Data.SOS; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + IR=sosfilt(reshape(squeeze(Data.SOS(ii,jj,:)),6,[])',impulse); + TF=fft(IR,Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Data.SOS = Obj.Data.SOS; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + IR=sosfilt(reshape(squeeze(Data.SOS(ii,jj,:)),6,[])',impulse); + TF=fft(IR,Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + Obj=SOFAupdateDimensions(Obj); + + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + + case 'TF' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + if sum(diff(diff(Obj.N))) + fs=max(Obj.N)*2; % irregular grid, find the smallest frequency difference + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + Nidx=Obj.N*N/fs+1; + Nsize=floor(N/2+1); + else + N=2*(length(Obj.N)-1); % regular grid (from an DFT probably), works for odd length only + fs=max(Obj.N)*2; + Nidx=1:length(Obj.N); + Nsize=length(Obj.N); + end + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=fs; + Obj.Data.SamplingRate_Units='hertz'; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(Nsize,1); + s(Nidx)=squeeze(Obj.Data.Real(ii,jj,:))+1i*squeeze(Obj.Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); + end + Obj.Data.Delay=zeros(1,Obj.API.R); + Obj.SourcePosition_Type=newObj.SourcePosition_Type; + Obj.SourcePosition_Units=newObj.SourcePosition_Units; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag'}); + if isfield(Obj.API.Dimensions,'Data') + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + end + elseif strcmp(newObj.GLOBAL_DataType,'TF') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType = newObj.GLOBAL_DataType; + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + + + case 'TF-E' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=max(Obj.N)*2; + Obj.Data.SamplingRate_Units='hertz'; + % convert sperical harmonics + if strcmpi(Obj.EmitterPosition_Type,'spherical harmonics') + [X,Y,Z]=sphere(60); + [azi_rad,ele_rad,radius]=cart2sph(X,Y,Z); + azi=azi_rad/pi*180; + ele=ele_rad/pi*180; + [azi,ele]=nav2sph(azi,ele); + radius=1.2*radius; + azi=azi(:); + ele=ele(:); + radius=radius(:); + + S = sph2SH([azi ele], sqrt(Obj.API.E)-1); + Obj.API.M=size(S,1); + Obj.SourcePosition=[azi ele radius]; + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degrees,degrees,metre'; + + Data.Real = zeros(Obj.API.M,2,Obj.API.N); + Data.Imag = zeros(Obj.API.M,2,Obj.API.N); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Data.Real(:,ii,jj)=S*squeeze(Obj.Data.Real(1,ii,jj,:)); + Data.Imag(:,ii,jj)=S*squeeze(Obj.Data.Imag(1,ii,jj,:)); + end + end + else +% Obj.EmitterPosition=Obj.SourcePosition; +% Obj.EmitterPosition_Type=Obj.SourcePosition_Type; +% Obj.EmitterPosition_Units=Obj.SourcePosition_Units; +% Data.Real = shiftdim(squeeze(Obj.Data.Real(1,:,:,:)),2); +% Data.Imag = shiftdim(squeeze(Obj.Data.Imag(1,:,:,:)),2); +% Obj.API.M=Obj.API.E; + error(['Converting ' Obj.GLOBAL_SOFAConventions ' to ' newObj.GLOBAL_SOFAConventions ' not supported yet']); + end + + if sum(diff(diff(Obj.N))) + fs=max(Obj.N)*2; % irregular grid, find the smallest frequency difference + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + Nidx=Obj.N*N/fs+1; + Nsize=floor(N/2+1); + else + N=2*(length(Obj.N)-1); % regular grid (from an DFT probably), works for odd length only + fs=max(Obj.N)*2; + Nidx=1:length(Obj.N); + Nsize=length(Obj.N); + end + + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(Nsize,1); + s(Nidx)=squeeze(Data.Real(ii,jj,:))+1i*squeeze(Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); + end + Obj.Data.Delay=zeros(Obj.API.M,Obj.API.R,1); + Obj.Data.SamplingRate=fs; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag'}); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + % convert sperical harmonics + if strcmpi(Obj.EmitterPosition_Type,'harmonics') + [X,Y,Z]=sphere(60); + [azi_rad,ele_rad,radius]=cart2sph(X,Y,Z); + azi=azi_rad/pi*180; + ele=ele_rad/pi*180; + [azi,ele]=nav2sph(azi,ele); + radius=1.2*radius; + azi=azi(:); + ele=ele(:); + radius=radius(:); + + S = sph2SH([azi ele], sqrt(Obj.API.E)-1); + Obj.API.M=size(S,1); + Obj.SourcePosition=radius; + Obj.SourcePosition_Type='spherical harmonics'; + Obj.SourcePosition_Units='metre'; + + oldObj.Data.Real = Obj.Data.Real; + oldObj.Data.Imag = Obj.Data.Imag; + Obj.Data.Real = zeros(Obj.API.M,2,Obj.API.N); + Obj.Data.Imag = zeros(Obj.API.M,2,Obj.API.N); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(:,ii,jj)=S*squeeze(oldObj.Data.Real(1,ii,jj,:)); + Obj.Data.Imag(:,ii,jj)=S*squeeze(oldObj.Data.Imag(1,ii,jj,:)); + end + end + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; + else + error('Conventions not supported'); + end + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + % no data conversion needed + end + + case 'FIR' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + IR=Obj.Data.IR; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + TF=fft(IR(ii,jj,:),Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + IR=Obj.Data.IR; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + TF=fft(IR(ii,jj,:),Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj=SOFAupdateDimensions(Obj); + + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + otherwise + error(['Turning ',oldConvention,' into ',... + newObj.GLOBAL_SOFAConventions,' not supported.']); + end +catch ME + rethrow(ME); + error(['Turning ',oldConvention,' into ',... + newObj.GLOBAL_SOFAConventions,' not supported.']); +end +Obj.SourcePosition=SOFAconvertCoordinates(Obj.SourcePosition,Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); +Obj.SourcePosition_Type=newObj.SourcePosition_Type; +Obj.SourcePosition_Units=newObj.SourcePosition_Units; +if strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics') && ~strcmpi(newObj.EmitterPosition_Type,'Spherical Harmonics') + Obj.EmitterPosition=[0 0 0]; + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; +elseif ~strcmpi(newObj.EmitterPosition_Type,'Spherical Harmonics') + Obj.EmitterPosition=SOFAconvertCoordinates(Obj.EmitterPosition,Obj.EmitterPosition_Type,newObj.EmitterPosition_Type,Obj.EmitterPosition_Units,newObj.EmitterPosition_Units); + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; +end +Obj.ListenerPosition=SOFAconvertCoordinates(Obj.ListenerPosition,Obj.ListenerPosition_Type,newObj.ListenerPosition_Type,Obj.ListenerPosition_Units,newObj.ListenerPosition_Units); +Obj.ListenerPosition_Type=newObj.ListenerPosition_Type; +Obj.ListenerPosition_Units=newObj.ListenerPosition_Units; +Obj.ReceiverPosition=SOFAconvertCoordinates(Obj.ReceiverPosition,Obj.ReceiverPosition_Type,newObj.ReceiverPosition_Type,Obj.ReceiverPosition_Units,newObj.ReceiverPosition_Units); +Obj.ReceiverPosition_Type=newObj.ReceiverPosition_Type; +Obj.ReceiverPosition_Units=newObj.ReceiverPosition_Units; +Obj=SOFAupdateDimensions(Obj); + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m new file mode 100644 index 0000000000000000000000000000000000000000..50b4f392c3e5971f5efc632389a978dee6cd7bc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m @@ -0,0 +1,66 @@ + function output = SOFAconvertCoordinates(input,input_type,output_type,~,~) +%SOFAconvertCoordinates +% output = SOFAconvertCoordinates(input,input_type,output_type), converts the specified coordinate variable to specified +% output_type and returns the results. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: type horizontal-polar removed (not defined in SOFA) (08.03.2021) +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAconvertCoordinates +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% check input +if strcmp(input_type,'cartesian')==0 && ... + strcmp(input_type,'spherical')==0 && ... + strcmp(input_type,'geodesic')==0 % && ... +% strcmp(input_type,'horizontal-polar')==0 + error('Specified "input_type" is not supported'); +end +if strcmp(output_type,'cartesian')==0 && ... + strcmp(output_type,'spherical')==0 && ... + strcmp(output_type,'geodesic')==0 % && ... +% strcmp(output_type,'horizontal-polar')==0 + error('Specified "output_type" is not supported'); +end + +output=input; +%% convert coordinates if necessary +if strcmp(output_type,input_type)==0 + temp=input; + switch input_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [temp(:,1),temp(:,2),temp(:,3)]=sph2cart(deg2rad(input(:,1)),deg2rad(input(:,2)),input(:,3)); +% case 'horizontal-polar' +% [temp(:,1),temp(:,3),temp(:,2)]=sph2cart(deg2rad(input(:,2)),deg2rad(input(:,1)),input(:,3)); +% temp(:,2)=-temp(:,2); + end + + output=temp; + switch output_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [output(:,1),output(:,2),output(:,3)]=cart2sph(temp(:,1),temp(:,2),temp(:,3)); + output(:,1:2)=rad2deg(output(:,1:2)); +% case 'horizontal-polar' +% % [output(:,2),output(:,1),output(:,3)]=cart2sph(temp(:,1),temp(:,3),-temp(:,2)); +% % output(:,1:2)=rad2deg(output(:,1:2)); +% % output(:,1)=-output(:,1); +% % output(:,2)= mod(output(:,2)+90,360)-90; +% [output(:,1),output(:,2),output(:,3)]=cart2sph(temp(:,1),temp(:,3),-temp(:,2)); +% [output(:,1),output(:,2)]=sph2hor(output(:,1),output(:,2)); + end +end + + + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m new file mode 100644 index 0000000000000000000000000000000000000000..127d1519f9a4d98205ff8ec4172f0ed0c40768ad --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m @@ -0,0 +1,35 @@ +function dbPath=SOFAdbPath(newPath) +% dbPath=SOFAdbPath(newPath) +% +% dbPath=SOFAdbPath returns the path to the directory containing +% HRTFs for demos and applications. The default path is: this_directory/../data/SOFA +% +% [...]=SOFAdbPath(newPath) sets the path to the directory for further calls +% of SOFAdbPath. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAstart +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedPath; + +if exist('newPath','var') + if strcmp(newPath,'reset') + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'data','SOFA'); + else + CachedPath=newPath; + end +elseif isempty(CachedPath) + % default: 'this_directory/../data/SOFA' + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'data','SOFA'); +end +dbPath=CachedPath; + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m new file mode 100644 index 0000000000000000000000000000000000000000..ba17308dab105a995a29dc8d681cf70c7c667fd1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m @@ -0,0 +1,32 @@ +function dbURL=SOFAdbURL(dbURL) +% dbURL=SOFAdbURL +% +% dbURL=SOFAdbURL returns the internet URL to the directory containing +% HRTFs. The default URL is http://www.sofacoustics.org/data. +% +% dbURL=SOFAdbURL(newURL) sets the internet URL to the newURL for further calls +% of SOFAdbURL. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAdbURL +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedURL; + +if exist('dbURL','var') + if strcmp(dbURL,'reset') + CachedURL='http://www.sofacoustics.org/data'; + else + CachedURL=dbURL; + end +elseif isempty(CachedURL) + CachedURL='http://www.sofacoustics.org/data'; +end +dbURL=CachedURL; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m new file mode 100644 index 0000000000000000000000000000000000000000..d8cf1c7130e7ae73636cb77218e779ba99d328e6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m @@ -0,0 +1,83 @@ +function output = SOFAdefinitions(varargin) +% output = SOFAdefinitions(varargin) +% +% SOFAdefinitions returns a struct containing definitions like the time +% format used in the API. +% +% SOFAdefinitions('dateFormat') returns the date format +% +% SOFAdefinitions('APIName') returns the APIName +% +% SOFAdefinitions('dimensions') returns the dimensions used in the API +% +% SOFAdefinitions('EOL') returns the end-of-line separator used in the API +% +% SOFAdefinitions('dateReference') returns the string with the reference +% for the date when stored as numeric (number of seconds elapsed) +% +% SOFAdefinitions('units') returns the units and their corresponding aliases +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAdefinitions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +definput.flags.type={'all','dateFormat','APIName','dimensions','EOL','dateReference','units'}; +[flags,kv]=SOFAarghelper({},definput,varargin); + +%% Return all definitions in a structure +if flags.do_all, + output.APIName = SOFAdefinitions('APIName'); + output.dateFormat = SOFAdefinitions('dateFormat'); + output.dimensions = SOFAdefinitions('dimensions'); + output.EOL = SOFAdefinitions('EOL'); + output.dateReference = SOFAdefinitions('dateReference'); + output.units=SOFAdefinitions('units'); +end + +%% name of the API +if flags.do_APIName, + output = 'ARI SOFA Toolbox for Matlab/Octave'; +end + +%% date string to use (see help datestr) +if flags.do_dateFormat, + output = 'yyyy-mm-dd HH:MM:SS'; +end + +%% EOL to use +if flags.do_EOL, + output = char(10); +end + +%% dimensions to use +if flags.do_dimensions, + output.M = 'M'; % Number of Measurements + output.R = 'R'; % Number of Receivers + output.N = 'N'; % Number of Samples or the way you represent your data + output.E = 'E'; % Number of Emitters + output.C = 'C'; % Coordinates + output.I = 'I'; % Singleton + output.S = 'S'; % size of the largest string +end + +%% reference for date when used as numeric (number of seconds elapsed) +if flags.do_dateReference, + output = '1970-01-01 00:00:00'; +end + +%% return units with defined aliases +if flags.do_units, + output.metre={'metres','meter','meters'}; + output.degree={'degrees'}; + output.second={'seconds'}; +end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m new file mode 100644 index 0000000000000000000000000000000000000000..e70a93b875909b89d2a09ba60ffd5b3c87dcaeec --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m @@ -0,0 +1,137 @@ +function [Obj, log] = SOFAexpand(Obj,VarName) +%SOFAexpand +% Obj = SOFAexpand(Obj) expands the singleton dimensions of all variables. +% Only variables will be expanded. Data and attributes won't. Note that Obj.API.Dimensions will be updated to the new dimensions. +% +% Obj = SOFAexpand(Obj,VarName) expands the singleton dimensions of the variable VarName. +% +% [Obj,log] = SOFAexpand(...) returns a log of expanded variables. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAexpand +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj,'nodata'); + +%% If VarName given, expand a single variable only +if ~exist('VarName','var'), + + %% Expand all variables + % create field names which should have dimensions + X=rmfield(Obj,{'Data','API'}); + if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end + Xf=fieldnames(X); + + % Update the dimensions structure w/o data + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.(Xf{ii})=varNew; + Obj.API.Dimensions.(Xf{ii})=dimNew; + log{end+1}=[Xf{ii} ' expanded to ' dimNew]; + end + end + + % Expand the dimensions of Data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.Data.(Xf{ii})=varNew; + Obj.API.Dimensions.Data.(Xf{ii})=dimNew; + log{end+1}=['Data.' Xf{ii} ' expanded to ' dimNew]; + end + end + + +else % Expand a single variable only + if isempty(strfind(VarName,'_')), % is an attribute --> not expandable + if strncmp(VarName,'Data.',length('Data.')) + % variable within the Data. structure + VarName=VarName(length('Data.')+1:end); + if isfield(OC.API.Dimensions.Data, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,VarName,dim); + if ~isempty(varNew), + Obj.Data.(VarName)=varNew; + Obj.API.Dimensions.Data.(VarName)=dimNew; + log{end+1}=['Data.' VarName ' expanded to ' dimNew]; + end + end + end + else + if isfield(OC.API.Dimensions, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,VarName,dim); + if ~isempty(varNew), + Obj.(VarName)=varNew; + Obj.API.Dimensions.(VarName)=dimNew; + log{end+1}=[VarName ' expanded to ' dimNew]; + end + end + end + end + end +end + +%% log variable +if length(log)>1, log=log(2:end); else log={}; end; + +%% expand a single variable +% Obj: the full SOFA object +% f: name of the variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expand(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.(f),ones([getdim(Obj,dN) 1])); + end + if ~exist('var','var'), var=[]; dN=[]; end; +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); + +%% expand a single Data variable +% Obj: the full SOFA object +% f: name of the Data variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expandData(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.Data.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.Data.(f),ones([getdim(Obj,dN) 1])); + end + if ~exist('var','var'), var=[]; dN=[]; end; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m new file mode 100644 index 0000000000000000000000000000000000000000..66a7a03b20af0db83d99642ba735336217235e15 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m @@ -0,0 +1,47 @@ +function [idx, azinew, elenew, rnew] = SOFAfind(Obj,azi,ele,r) +% SOFAfind +% [idx, azi, ele, r] = SOFAfind(Obj, azi, ele, r) finds the indecies to +% the HRTFs from OBJ according to the trajectory given in AZI, ELE, R. +% Input: +% Obj: SOFA object containing HRTFs +% azi, ele: direction (in degrees) for azimuth and elevation +% r: optional radius. If not provided, radius will be ignored. +% +% Output: +% idx: index of the filters (corresponds to AZI and ELE) +% azi, ele: azimuth and elevation of the actual position (degrees) +% r: actual radius +% + +% #Author: Piotr Majdak (2019) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - SOFAfind +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + +%% create a 2D-grid with nearest positions +if ~exist('r','var'), + r=1; + Obj.SourcePosition(:,3)=r; +end +pos=SOFAconvertCoordinates(Obj.SourcePosition,'spherical','cartesian'); +idx=zeros(length(azi),1); +for ii=1:length(azi) + [t(:,1),t(:,2),t(:,3)] = sph2cart(deg2rad(azi(ii)),deg2rad(ele(ii)),r); + dist = sum((pos-repmat(t,size(pos,1),1)).^2,2); + [~,idx(ii)]=min(dist); +end + +%% Output +% actually used angles +azinew = Obj.SourcePosition(idx,1); +elenew = Obj.SourcePosition(idx,2); +rnew = Obj.SourcePosition(idx,3); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..4eef2508553f6bd0c0ac892efc16b878d22b6f3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m @@ -0,0 +1,139 @@ +function Obj = SOFAgetConventions(sofaconventions,flags,version) +%SOFAgetConventions +% +% List = SOFAgetConventions() returns a list with supported conventions. +% +% Obj = SOFAgetConventions(sofaconvention) returns a SOFA object +% with all metadata and data for the corresponding sofaconvention. Obj +% will be empty if sofaconventions is not supported. +% +% Obj = SOFAgetConventions(sofaconvention, flags) returns only selected +% metadata for the corresponding sofaconvention with the following encoding: +% m: mandatory +% r: readonly +% a: all (default) +% +% Obj = SOFAgetConventions(sofaconvention, version) returns only the selected +% version of the convention. +% +% Obj = SOFAgetConventions(sofaconvention, flag, version) returns only the selected +% version and metadata. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAgetConventions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Cache +persistent AllObj; + +%% If flags not provided, return the conventions with all metadata +if ~exist('version','var') + if ~exist('flags','var') + flags='a'; % no flags, no version --> flags = a, version = any. + else + switch flags % no version, check if flags is flags or version + case {'a', 'm', 'r'} + % flags is flags --> do nothing + otherwise + version=flags; % flags is version --> copy to version + flags='a'; + end + end +end + + +%% If sofaconventions not provided, return the list with supported conventions +if ~exist('sofaconventions','var') + p=mfilename('fullpath'); + d=dir([p(1:length(p)-length(mfilename)) 'conventions' filesep '*_m_*.mat']); + Obj={}; + for ii=1:length(d) + dn=d(ii).name; + idx=strfind(dn,'_'); + Obj{ii,1}=dn(1:idx(1)-1); + end + Obj=unique(Obj); + AllObj=[]; + return; +end + +%% Load cached object + +if isfield(AllObj,flags) + if isfield(AllObj.(flags).Obj,'GLOBAL_SOFAConventions') + if strcmp(AllObj.(flags).Obj.GLOBAL_SOFAConventions,sofaconventions) + if ~exist('version','var') + Obj=AllObj.(flags).Obj; % return cached convention object + else + if strcmp(AllObj.(flags).Obj.GLOBAL_SOFAConventionsVersion,version) + Obj=AllObj.(flags).Obj; % return cached convention object + end + end + end + end +end + +if ~exist('Obj','var') + % cached object not loaded yet + p=mfilename('fullpath'); + if exist('version','var') + % load a specific version but do not store in the cache + if ~isempty(dir([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '_' flags '_' version '.mat'])) + load([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '_' flags '_' version '.mat']); + else + error(['Convention ' sofaconventions ' with the version ' version ' not found.']); + end + else + allver=dir(fullfile(p(1:length(p)-length(mfilename)), 'conventions' , [sofaconventions '_' flags '_*.mat'])); + if isempty(allver) + warning(['Convention ' sofaconventions ' not found.']'); + Obj=[]; + else + vermax='0.0'; + idxmax=0; + for ii=1:length(allver) + x=load([p(1:length(p)-length(mfilename)) 'conventions' filesep allver(ii).name]); + if compareversions(x.Obj.GLOBAL_SOFAConventionsVersion,vermax)>0 + vermax=x.Obj.GLOBAL_SOFAConventionsVersion; + idxmax=ii; + end + end + % store in cache + AllObj.(flags)=load([p(1:length(p)-length(mfilename)) 'conventions' filesep allver(idxmax).name]); + Obj=AllObj.(flags).Obj; % return the cached version + end + end +end + +%% Overwrite some special fields +if isfield(Obj,'GLOBAL_DateCreated'), Obj.GLOBAL_DateCreated=datestr(now,SOFAdefinitions('dateFormat')); end +if isfield(Obj,'GLOBAL_APIVersion'), Obj.GLOBAL_APIVersion=SOFAgetVersion; end +if isfield(Obj,'GLOBAL_APIName'), Obj.GLOBAL_APIName=SOFAdefinitions('APIName'); end + +end + +function res=compareversions(ver1, ver2) + + [~,maj1,min1]=fileparts(ver1); + [~,maj2,min2]=fileparts(ver2); + maj1=str2num(maj1); + min1=str2num(min1(2:end)); + maj2=str2num(maj2); + min2=str2num(min2(2:end)); + if maj1>maj2 + res=1; % ver1 > ver2 + elseif maj1==maj2 && min1>min2 + res=1; % ver1 > ver2 + elseif maj2==maj2 && min1==min2 + res=0; % ver1 == ver2 + else + res=-1; % ver < ver2 + end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m new file mode 100644 index 0000000000000000000000000000000000000000..df4b8d814ad546db955081fbc1b4a55bb085c2d5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m @@ -0,0 +1,29 @@ +function results = SOFAgetVersion(flag) +%SOFAGETVERSION +% version = SOFAgetVersion() returns the version of the SOFA Toolbox API +% +% version = SOFAgetVersion('API') does the same. +% +% version = SOFAgetVersion('SOFA') returns the version of the SOFA supported by this Toolbox API. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAgetVersion +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~exist('flag','var') + flag='API'; +end + +switch flag + case 'API' + results = '2.0'; + case 'SOFA' + results = '2.0'; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m new file mode 100644 index 0000000000000000000000000000000000000000..adc80e62a97661bbd6f14cea66311d770c0416bd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m @@ -0,0 +1,87 @@ +function SOFAinfo(Obj) +% SOFAinfo(Obj) gathers (mandatory) information about the SOFA object and +% display it. For SimpleFreeFieldHRIR some more details are displayed. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Global fields + +disp('### SOFAinfo: ###') +disp([Obj.GLOBAL_Conventions ' ' Obj.GLOBAL_Version]) +disp(['Conventions: ' Obj.GLOBAL_SOFAConventions ' ' Obj.GLOBAL_SOFAConventionsVersion]) +disp(['API: ' Obj.GLOBAL_APIName ' ' Obj.GLOBAL_APIVersion]) +disp(['Data Type: ' Obj.GLOBAL_DataType]) +disp(['Room Type: ' Obj.GLOBAL_RoomType]) +disp(['Date Created: ' Obj.GLOBAL_DateCreated]) +disp(['Date Modified: ' Obj.GLOBAL_DateModified]) +disp(['Author Contact: ' Obj.GLOBAL_AuthorContact]) +disp(['Organization: ' Obj.GLOBAL_Organization]) +disp(['License: ' Obj.GLOBAL_License]) +disp(['Title: ' Obj.GLOBAL_Title]) + + +%% Conventions dependant fields + +switch Obj.GLOBAL_SOFAConventions + + case 'SimpleFreeFieldHRIR' +disp(['Datebase Name: ' Obj.GLOBAL_DatabaseName]) + disp(' ') + disp(['Measurement details (' Obj.GLOBAL_SOFAConventions '):']); + disp('--------------------'); + disp(['Number of azimuth angles: ' num2str(length(unique(Obj.SourcePosition(:,1))))]); + disp(['Number of elevation angles: ' num2str(length(unique(Obj.SourcePosition(:,2))))]); + disp(['Number of radii: ' num2str(length(unique(Obj.SourcePosition(:,3))))]); + if isfield(Obj.Data,'SamplingRate') + disp(['Sampling Rate: ' num2str(Obj.Data.SamplingRate) ' ' Obj.Data.SamplingRate_Units]) + + end + disp(['Listener Short Name: ' Obj.GLOBAL_ListenerShortName]) + + if size(Obj.ListenerPosition,1)==1 + disp(['Listener Position: ', num2str(Obj.ListenerPosition) ' ' Obj.ListenerPosition_Units]); + else + disp([num2str(size(Obj.ListenerPosition,1)) ' Listener Positions']); + disp([' from ' num2str(Obj.ListenerPosition(1,:)) ' [' Obj.ListenerPosition_Units ']']); + disp([' to ' num2str(Obj.ListenerPosition(end,:)) ' [' Obj.ListenerPosition_Units ']']); + end + + if size(Obj.ListenerView,1)==1 + disp(['Listener View: ', num2str(Obj.ListenerView) ' ' Obj.ListenerView_Units]); + else + disp([num2str(size(Obj.ListenerPosition,1)) ' Listener Views']); + disp([' from ' num2str(Obj.ListenerView(1,:)) ' [' Obj.ListenerView_Units ']']); + disp([' to ' num2str(Obj.ListenerView(end,:)) ' [' Obj.ListenerView_Units ']']); + end + + if size(Obj.ReceiverPosition,1)==1 + disp(['Receiver Position: ', num2str(Obj.ReceiverPosition) ' ' Obj.ReceiverPosition_Units]); + else + disp([num2str(size(Obj.ReceiverPosition,1)) ' Receiver Positions']); + disp([' from ' num2str(Obj.ReceiverPosition(1,:)) ' [' Obj.ReceiverPosition_Units ']']); + disp([' to ' num2str(Obj.ReceiverPosition(end,:)) ' [' Obj.ReceiverPosition_Units ']']); + end + disp(['Receiver Position Type: ' Obj.ReceiverPosition_Type]) + + if size(Obj.SourcePosition,1)==1 + disp(['Source Position: ', num2str(Obj.SourcePosition) ' ' Obj.SourcePosition_Units]); + else + disp([num2str(size(Obj.SourcePosition,1)) ' Source Positions']); + disp([' from ' num2str(Obj.SourcePosition(1,:)) ' [' Obj.SourcePosition_Units ']']); + disp([' to ' num2str(Obj.SourcePosition(end,:)) ' [' Obj.SourcePosition_Units ']']); + end + disp(['Source Position Type: ' Obj.SourcePosition_Type]) + otherwise + % fill with conventions and disp commands if you feel motivated +end + +disp('### end ###') diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..63192cfef57ac8d3a41745d2ce791fcc93ed9e37 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m @@ -0,0 +1,187 @@ +function Obj = SOFAload(fn,varargin) +%SOFALOAD +% Obj = SOFAload(FN) reads the SOFA object OBJ with all data from a SOFA file FN. +% +% FN can point to a remote file (containing '://') or to a local file: +% Remote file: FN will be downloaded to a temporary directory and loaded. +% Local file: If existing, will be loaded. If not existing, it will be downloaded from the internet repository given by SOFAdbURL. For this, FN must begin with the local HRTF directory given by SOFAdbPath. +% +% Obj = SOFAload(FN,'nodata') ignores the "Data." variables and loads metadata only (variables and attributes). +% +% Obj = SOFAload(FN,[START COUNT]) loads only COUNT number of measurements (dimension M) beginning with the index START. For remote files, or local but not existing files, the full file will be downloaded. +% +% Obj = SOFAload(FN,[START1 COUNT1],DIM1,[START2 COUNT2],DIM2,...) loads only COUNT1 number of data in dimension DIM1 beginning with the index START1, COUNT2 number of data in dimension DIM2 with the index START2 and so on. +% +% Obj = SOFAload(FN,...,'nochecks') loads the file but does not perform any checks for correct conventions. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAload +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% ----- Input parameters ------------------------------------------------ +inputargs={}; % for setting flags with SOFAarghelper +pDims=''; % for partial loading +pDimRange=[]; % for partial loading +jj=1; kk=1; ll=1; +for ii=1:length(varargin) + if isnumeric(varargin{ii}) + pDimRange(jj,:)=varargin{ii}; + jj=jj+1; + if ii==1 + inputargs{kk}=varargin{ii}; + kk=kk+1; + end + elseif strfind('MREN',varargin{ii}) + pDims(ll)=varargin{ii}; + ll=ll+1; + elseif strcmp(varargin{ii},'nochecks') + inputargs{kk}=varargin{ii}; + elseif strcmp(varargin{ii},'nodata') + inputargs{kk}=varargin{ii}; + kk=kk+1; + end +end +if ~isempty(pDimRange) && isempty(pDims) + pDims='M'; +end + +% Set flags with SOFAarghelper +definput.keyvals.Index = []; +definput.flags.type = {'data','nodata'}; +definput.flags.data = {'checks','nochecks'}; +[flags,kv] = SOFAarghelper({'Index'},definput,inputargs); + +% Check number of input arguments for partial loading +if ~(length(pDims)==size(pDimRange,1) || isempty(kv.Index)) + error('Missing dimension or range for partial loading'); +end +% Check file name +fn = SOFAcheckFilename(fn); +% Check if local or remote and download if necessary +if strfind(fn,'://') + % remote path: download as temporary + newfn = [tempname '.sofa']; + urlwrite(fn, newfn); +else + newfn = fn; + if ~exist(fn,'file') % file does not exist? + warning('SOFA:load',['File not found: ' strrep(fn,'\','\\')]); + % local path: replace SOFAdbPath by SOFAdbURL, download to SOFAdbPath + if length(fn)>length(SOFAdbPath) % fn is longer than SOFAdbPath? + if strcmp(SOFAdbPath,fn(1:length(SOFAdbPath))) % fn begins with SOFAdbPath + % create dir if not existing + if ~exist(fileparts(newfn),'dir'), + [success,msg] = mkdir(fileparts(newfn)); + if success~=1, error(msg); end + end + webfn = fn(length(SOFAdbPath)+1:end); + webfn(strfind(webfn,'\'))='/'; + webfn = [SOFAdbURL regexprep(webfn,' ','%20')]; + disp(['Downloading ' fn(length(SOFAdbPath)+1:end) ' from ' SOFAdbURL]); + [f,stat] = urlwrite(webfn,fn); + if ~stat + error(['Could not download file: ' webfn]); + end + else % fn not existing and not beginning with SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + else % fn not existing and shorter than SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + end +end + + +%% ----- Load SOFA file -------------------------------------------------- +if flags.do_nodata + Obj = NETCDFload(newfn,'nodata'); +elseif flags.do_data + try + if isempty(kv.Index), + Obj = NETCDFload(newfn,'all'); + else + Obj = NETCDFload(newfn,pDimRange,pDims); + end + catch me + error(['Error loading the file: ' newfn 13 me.message]); + end +end + + +%% ----- Checking of loaded data ----------------------------------------- +% Return if no checks should be performed +if flags.do_nochecks + return; +else + + % ----- Check for SOFA conventions ----- + if ~isfield(Obj,'GLOBAL_Conventions') || ~strcmp(Obj.GLOBAL_Conventions,'SOFA') + error('File is not a valid SOFA file'); + end + if ~isfield(Obj,'GLOBAL_SOFAConventions') + error('Information about SOFA conventions is missing'); + end + try + ObjTemplate = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + if isempty(ObjTemplate), + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + catch + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + + % ----- Check if DataType is present ----- + if ~isfield(Obj,'GLOBAL_DataType') + error('DataType is missing'); + end + + % ----- Check if mandatory variables are present ----- + for field = fieldnames(ObjTemplate)' + field = field{:}; + if ~isfield(Obj,field) + Obj.(field) = ObjTemplate.(field); + if ~strfind(field,'_') % if `_` is missing it is a dimension + Obj.API.Dimensions.(field) = ObjTemplate.API.Dimensions.(field); + end + warning('SOFA:load',[field ' was missing, set to default']); + end + end + + % ---- If data loaded, check for correct data format ----- + if ~flags.do_nodata + if ~isfield(Obj,'Data') + error('Data is missing'); + end + for field = fieldnames(ObjTemplate.Data)' + field = field{:}; + if ~isfield(Obj.Data,field) + Obj.Data.(field) = ObjTemplate.Data.(field); + Obj.API.Dimensions.Data.(field) = ... + ObjTemplate.API.Dimensions.Data.(field); + warning('SOFA:load',['Data.' field ' was missing, set to default']); + end + end + Obj = SOFAupdateDimensions(Obj); + end + + % Remove undesired attribute of NetCDF files, if existing + if isfield(Obj,'GLOBAL__NCProperties'), Obj=rmfield(Obj,'GLOBAL__NCProperties'); end + + % ----- Ensure backwards compatibility ----- + % TODO: is the while loop necessary, or could be handled just by calling + % SOFAupgradeConventions(Obj) once? + modified = 1; + while modified + [Obj,modified] = SOFAupgradeConventions(Obj); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..36c5e5fbcdec7da9c6dd3157379052a793c274cd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m @@ -0,0 +1,154 @@ +function [C, log] = SOFAmerge(A,B) +%SOFAmerge +% [C, log] = SOFAmerge(A, B) merges the SOFA objects A and B to a single one, C. +% +% A and B are structs containing the data and meta. A and B +% must be of the same SOFA conventions. +% +% C is a struct containing merged data +% log contains log data + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupdateDimensions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +if ~strcmp(A.GLOBAL_SOFAConventions,B.GLOBAL_SOFAConventions) + error('Both SOFA objects must use the same SOFA conventions'); +end +if A.API.N~=B.API.N + error('Data size of both SOFA objects must be the same'); +end +Def = SOFAdefinitions; +log={''}; +OC = SOFAgetConventions(A.GLOBAL_SOFAConventions,'a'); + +%% Update dimensions +A=SOFAupdateDimensions(A); +B=SOFAupdateDimensions(B); + +%% create field names which have to be checked +C=rmfield(B,{'API','Data'}); +if isfield(C,'PRIVATE'), C=rmfield(C,'PRIVATE'); end +Bf=fieldnames(C); + +%% Copy and merge metadata variables +C=A; +for ii=1:size(Bf,1) + if ~isfield(A,Bf{ii}) + C.(Bf{ii}) = B.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.(Bf{ii}),B.(Bf{ii})), + C.(Bf{ii}) = B.(Bf{ii}); % content the same, no conflict + else + switch Bf{ii} + case 'GLOBAL_TimeCreated' % use the oldest date + dateNew=datenum(A.GLOBAL_TimeCreated,Def.dateFormat); + if datenum(B.GLOBAL_TimeCreated,Def.dateFormat)<dateNew, dateNew=datenum(B.GLOBAL_TimeCreated,Def.dateFormat); end; + C.(Bf{ii}) = datestr(dateNew,Def.dateFormat); + log{end+1}=[Bf{ii} ' set to ' C.(Bf{ii})]; + case 'GLOBAL_TimeModified' % now + C.(Bf{ii}) = datestr(now,Def.dateFormat); + log{end+1}=[Bf{ii} ' updated']; + otherwise + C.(Bf{ii}) = [A.(Bf{ii}) '; ' B.(Bf{ii})]; % concatate [A; B] + log{end+1}=[Bf{ii} ' merged']; + end + end + else % a variable + if isfield(OC.API.Dimensions, Bf{ii}) % is a known variable? + AExp=SOFAexpand(A,Bf{ii}); + BExp=SOFAexpand(B,Bf{ii}); + dim=strfind(AExp.API.Dimensions.(Bf{ii}),'M'); + if isempty(dim), + error([Bf{ii} ' can not be merged because it does not depend on M']); + end + C.(Bf{ii})=cat(dim,AExp.(Bf{ii}),BExp.(Bf{ii})); + log{end+1}=[Bf{ii} ' expanded and merged']; + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.(Bf{ii}),'M'); + if ~isempty(dim), + C.(Bf{ii})=cat(dim,A.(Bf{ii}),B.(Bf{ii})); % depends on M, merge + log{end+1}=[Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.(Bf{ii})==B.(Bf{ii}))==1, + C.(Bf{ii})=A.(Bf{ii}); + log{end+1}=[Bf{ii} ' identical']; + else + error([Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Copy and merge Data variables +Bf=fieldnames(B.Data); +for ii=1:size(Bf,1) + if ~isfield(A.Data,Bf{ii}) + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.Data.(Bf{ii}),B.Data.(Bf{ii})), + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % content the same, no conflict + else + C.Data.(Bf{ii}) = [A.Data.(Bf{ii}) '; ' B.Data.(Bf{ii})]; % concatate [A; B] + log{end+1}=['Data.' Bf{ii} ' merged']; + end + else % a variable in Data + if isfield(OC.API.Dimensions.Data,Bf{ii}) % is a known variable? + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); % is a matrix + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if all(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Update the new dimensions and finish +C=SOFAcompact(C); +C=SOFAupdateDimensions(C); +if length(log)>1, log=log(2:end); else log={}; end; + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m new file mode 100644 index 0000000000000000000000000000000000000000..7541ffac9f25356c5ccfc7e8e15dc9b92e6cd945 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m @@ -0,0 +1,463 @@ +function SOFAplotGeometry(Obj,varargin) +% SOFAplotGeometry(Obj) plots the geometry found in the Obj. +% +% SOFAplotGeometry(Obj, index) plots the geometry for the measurements +% given in the index. +% +% Supported conventions: +% SimpleFreeFieldHRIR +% SimpleFreeFieldHRTF +% SingleRoomDRIR +% FreeFieldDirectivityTF +% some special cases of GeneralFIR. +% +% Parameter +% 'index' measurement to be plotted. Default: 1:Obj.API.M +% 'normalize' normalize view and up vectors +% 'SHorder' order of spherical harmonics +% 'SHm' m of shperical harmonics +% 'normalize' normalize view and up vectors +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: bug fixed when extracting LU (listener up) coordinates (28.12.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.keyvals.index=1:Obj.API.M; +definput.keyvals.shorder=Inf; +definput.keyvals.shm=Inf; +definput.flags.normalize={'normalize'}; +argin=varargin; +for ii=1:length(argin) + if ischar(argin{ii}), argin{ii}=lower(argin{ii}); end +end +[flags,kv] = SOFAarghelper({'index','shorder','shm'},definput,argin); +index = kv.index; +SHorder=kv.shorder; +SHm=kv.shm; +flags.do_normalize = flags.normalize; + +if any(index > Obj.API.M) + error(['Index out of range. Only ', num2str(Obj.API.M), ... + ' measurement(s) performed.']) +elseif any(index < 1) + error('Choose index to be >= 1.') +end + +switch Obj.GLOBAL_SOFAConventions +%% + case {'SimpleFreeFieldHRTF','SimpleFreeFieldHRIR','SingleRoomDRIR','FreeFieldDirectivityTF','GeneralFIR','GeneralTFE','FreeFieldHRIR','FreeFieldHRTF','GeneralTF-E'} + % Expand entries to the same number of measurement points + Obj = SOFAexpand(Obj); + % See if the room geometry is specified + if strcmpi(Obj.GLOBAL_RoomType,'shoebox') + x = min(Obj.RoomCornerA(1), Obj.RoomCornerB(1)); + xd = max(Obj.RoomCornerA(1), Obj.RoomCornerB(1)); + y = min(Obj.RoomCornerA(2), Obj.RoomCornerB(2)); + yd = max(Obj.RoomCornerA(2), Obj.RoomCornerB(2)); + w = xd - x; + h = yd - y; + figure('Position',[1 1 w*1.2 h]*100); + box on; hold on; + % plot the room + rectangle('Position',[x y w h]); + else + figure; hold on; + end + + legendEntries = []; + title(sprintf('%s, %s',Obj.GLOBAL_SOFAConventions,Obj.GLOBAL_RoomType)); + % Get ListenerPosition, ReceiverPosition, SourcePosition, and + % EmitterPosition + % NOTE: ListenerPosition is set to [0 0 0] for SimpleFreeFieldHRIR + LP = SOFAconvertCoordinates(Obj.ListenerPosition(index,:),Obj.ListenerPosition_Type,'cartesian'); + if ~(strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics')) + if size(Obj.ReceiverPosition,3)==1, idx=1; else idx=index; end + RP = SOFAconvertCoordinates(Obj.ReceiverPosition(:,:,idx),Obj.ReceiverPosition_Type,'cartesian'); + end + if size(Obj.SourcePosition,1)==1, idx=1; else idx=index; end + SP = SOFAconvertCoordinates(Obj.SourcePosition(idx,:),Obj.SourcePosition_Type,'cartesian'); + if ~(strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics')) + if size(Obj.EmitterPosition,3)==1, idx=1; else idx=index; end + EP = SOFAconvertCoordinates(Obj.EmitterPosition(:,:,idx),Obj.EmitterPosition_Type,'cartesian'); + end + if isfield(Obj,'ListenerView') + if size(Obj.ListenerView,1)==1, idx=1; else idx=index; end + LV = SOFAconvertCoordinates(Obj.ListenerView(idx,:),Obj.ListenerView_Type,'cartesian'); + end + if isfield(Obj,'ListenerUp') + try + if size(Obj.ListenerUp,1)==1, idx=1; else idx=index; end + LU = SOFAconvertCoordinates(Obj.ListenerUp(idx,:),Obj.ListenerUp_Type,'cartesian'); + catch + % if listerUp_type is not defined try using listenerView_type + % instead + if size(Obj.ListenerUp,1)==1, idx=1; else idx=index; end + LU = SOFAconvertCoordinates(Obj.ListenerUp(idx,:),Obj.ListenerView_Type,'cartesian'); + end + end + if isfield(Obj,'SourceView') + if size(Obj.SourceView,1)==1, idx=1; else idx=index; end + SV = SOFAconvertCoordinates(Obj.SourceView(idx,:),Obj.SourceView_Type,'cartesian'); + end + if isfield(Obj,'SourceUp') + try + if size(Obj.SourceUp,1)==1, idx=1; else idx=index; end + SU = SOFAconvertCoordinates(Obj.SourceUp(idx,:),Obj.SourceUp_Type,'cartesian'); + catch + if size(Obj.SourceUp,1)==1, idx=1; else idx=index; end + SU = SOFAconvertCoordinates(Obj.SourceUp(idx,:),Obj.SourceView_Type,'cartesian'); + end + end + % Use only unique listener and source positons + caseString = ''; + uniquePoints = [LP SP]; + if exist('LV') + uniquePoints = [uniquePoints LV]; + caseString = strcat(caseString , 'LV'); + end + if exist('LU') + uniquePoints = [uniquePoints LU]; + caseString = strcat(caseString, 'LU'); + end + if exist('SV') + uniquePoints = [uniquePoints SV]; + caseString = strcat(caseString, 'SV'); + end + if exist('SU') + uniquePoints = [uniquePoints SU]; + caseString = strcat(caseString, 'SU'); + end + + uniquePoints = unique(uniquePoints,'rows'); + switch caseString + case '' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + case 'LV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + case 'LVLU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); +% LU = uniquePoints(:,7:9); % I think this was a bug (miho) + LU = uniquePoints(:,10:12); + case 'LVLUSV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + LU = uniquePoints(:,10:12); + SV = uniquePoints(:,13:15); + case 'SV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + SV = uniquePoints(:,7:9); + case 'SVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + SV = uniquePoints(:,7:9); + SU = uniquePoints(:,10:12); + case 'LVSV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + SV = uniquePoints(:,10:12); + case 'LVSVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + SV = uniquePoints(:,10:12); + SU = uniquePoints(:,13:15); + case 'LVLUSVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + LU = uniquePoints(:,10:12); + SV = uniquePoints(:,13:15); + SU = uniquePoints(:,16:18); + otherwise + error('This SOFAConventions is not supported for plotting'); + end + + % Plot ListenerPosition + legendEntries(end+1) = plot3(LP(:,1),LP(:,2),LP(:,3),'ro','MarkerFaceColor','r','MarkerSize',5); + if strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics') + maxSHorder = sqrt(Obj.API.R)-1; + % set SHorder to max if user didn't specify it + if isinf(SHorder) + SHorder = maxSHorder; + end + % check if chosen SHorder is possible + if SHorder > maxSHorder + error(['Chosen SHorder not possibile, only orders up to ', ... + num2str(maxSHorder), ' possible.']) + elseif SHorder < 0 + error('Chosen SHorder not possibile, as it must be positive.') + end + x0 = Obj.ListenerPosition(1,1); + y0 = Obj.ListenerPosition(1,2); + z0 = Obj.ListenerPosition(1,3); + + % check for m given by the user and if it is possible + if isinf(SHm) + % if not set to some value + SHm = -floor(1/2 * SHorder); + elseif abs(SHm) > SHorder + error(['Chosen SHm not possibile, must be in range of abs(', ... + num2str(SHorder), ').']) + end + % if possibile set SHmForPlotting + SHmForPlotting = power(SHorder,2)+SHorder+SHm+1; + + [X,Y,Z] = sphere(50); + [azi_rad,elev_rad,~] = cart2sph(X,Y,Z); + azi_length =size(azi_rad,1); + elev_length=size(elev_rad,1); + azi= azi_rad/pi*180; + elev = elev_rad/pi*180; + azi = azi(:); + elev = elev(:); + + S = sph2SH([azi,elev], SHorder); + S = S(:,SHmForPlotting); + S = reshape(S,[azi_length,elev_length]); + + r_sphere = 0.7*max(max(S))*randi(2,size(S)); + r = abs(S) + r_sphere; + + [D_x,D_y,D_z] = sph2cart(azi_rad,elev_rad,abs(r)); + legendEntries(end+1) = surf(D_x+x0,D_y+y0,D_z+z0,Y,'LineStyle','none','FaceAlpha',0.09); +% elseif strcmpi(Obj.ReceiverPosition_Type,'spherical') +% S = sqrt(Obj.API.R-1); +% x0 = Obj.ListenerPosition(1,1); +% y0 = Obj.ListenerPosition(1,2); +% theta = -pi : 0.01 : pi; +% r = 1; +% phi = sin(S*theta); +% phi_negativ = sin(-S*theta); +% +% [x,y] = pol2cart(theta,(r*(1+ abs(phi)+ abs(phi_negativ)))./3); +% legendEntries(end+1)=plot(x+x0,y+y0,'LineStyle','--','Color',[0.741 0.747 0.741]); +% +% % text(x0,y0+r,['Order: ',num2str(S)],'HorizontalAlignment',... +% % 'center','VerticalAlignment','bottom') + + else + % Plot ReceiverPositon (this is plotted only for the first ListenerPosition) + if ndims(RP)>2 + % If ReceiverPosition has more than two dimensions reduce it to the first + % ListenerPosition + RP = shiftdim(RP,2); + RP = squeeze(RP(1,:,:)); + RP = reshape(RP,[size(Obj.ReceiverPosition,1), Obj.API.C]); + end + legendEntries(end+1) = plot3(LP(1,1)+RP(1,1), LP(1,2)+RP(1,2), LP(1,3)+RP(1,3),'r*','MarkerSize',8); + for ii=2:size(RP,1) + plot3(LP(1,1)+RP(ii,1), LP(1,2)+RP(ii,2), LP(1,3)+RP(ii,3),'r*','MarkerSize',8); + end + end + % Plot SourcePosition + legendEntries(end+1)=plot3(SP(:,1),SP(:,2),SP(:,3),'bd','MarkerSize',7); + % Plot EmitterPositions depending on Type + if strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics') + maxSHorder = sqrt(Obj.API.E)-1; + % set SHorder to max if user didn't specify it + if isinf(SHorder) + SHorder = maxSHorder; + end + % check if chosen SHorder is possible + if SHorder > maxSHorder + error(['Chosen SHorder not possibile, only orders up to ', ... + num2str(maxSHorder), ' possible.']) + elseif SHorder < 0 + error('Chosen SHorder not possibile, as it must be positive.') + end + x0 = Obj.SourcePosition(1,1); + y0 = Obj.SourcePosition(1,2); + z0 = Obj.SourcePosition(1,3); + + % check for m given by the user + if isinf(SHm) + SHm = -floor(1/2 * SHorder); + elseif abs(SHm) > SHorder + error(['Chosen SHm not possibile, must be in range of abs(', ... + num2str(SHorder), ').']) + end + % if possibile set SHmForPlotting + SHmForPlotting = power(SHorder,2)+SHorder+SHm+1; + + [X,Y,Z] = sphere(50); + [azi_rad,elev_rad,~] = cart2sph(X,Y,Z); + azi_length =size(azi_rad,1); + elev_length=size(elev_rad,1); + azi= azi_rad/pi*180; + elev = elev_rad/pi*180; + azi = azi(:); + elev = elev(:); + + S = sph2SH([azi,elev], SHorder); + S = S(:,SHmForPlotting); + S = reshape(S,[azi_length,elev_length]); + + r_sphere = 0.7*max(max(S))*randi(2,size(S)); + r = abs(S) + r_sphere; + + [D_x,D_y,D_z] = sph2cart(azi_rad,elev_rad,abs(r)); + legendEntries(end+1) = surf(D_x+x0,D_y+y0,D_z+z0,Y,'LineStyle','none','FaceAlpha',0.09); + +% elseif strcmpi(Obj.EmitterPosition_Type,'spherical') +% S = sqrt(Obj.API.R-1); +% x0 = Obj.SourcePosition(1,1); +% y0 = Obj.SourcePosition(1,2); +% theta = -pi : 0.01 : pi; +% r = 1; +% phi = sin(S*theta); +% phi_negativ = sin(-S*theta); +% +% [x,y] = pol2cart(theta,(r*(1+ abs(phi)+ abs(phi_negativ)))./3); +% legendEntries(end+1)=plot(x+x0,y+y0,'LineStyle','--','Color',[0.741 0.747 0.741]); +% +% % text(x0,y0+r,['Order: ',num2str(S)],'HorizontalAlignment',... +% % 'center','VerticalAlignment','bottom') + + else + % Plot EmitterPosition + if ndims(EP)>2 + % If EmitterPosition has more than two dimensions reduce it to the first + % ListenerPosition + EP = shiftdim(EP,2); + EP = squeeze(EP(1,:,:)); + EP = reshape(EP,[size(Obj.EmitterPosition,1), Obj.API.C]); + end + % plot Emitters for first Source + legendEntries(end+1) = plot3(SP(1,1)+EP(1,1), SP(1,2)+EP(1,2), SP(1,3)+EP(1,3),'b+','MarkerSize',8); + for ii=2:size(EP,1) + plot3(SP(1,1)+EP(ii,1), SP(1,2)+EP(ii,2), SP(1,3)+EP(ii,3),'b+','MarkerSize',8); + end + % plot all Emitters for each Source + for jj=2:size(SP,1) + for ii=1:size(EP,1) + plot3(SP(jj,1)+EP(ii,1), SP(jj,2)+EP(ii,2), SP(jj,3)+EP(ii,3),'b+'); + end + end + end + if exist('LV','var') + % Plot ListenerView + LV=unique(LV,'rows'); + for ii = 2:size(LV,1) + % Scale size of ListenerView vector smaller + if flags.do_normalize + LV(ii,:) = LV(ii,:)./norm(LV(ii,:)); + end + % Plot line for ListenerView vector + quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LV(ii,1),LV(ii,2),LV(ii,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if flags.do_normalize + LV(1,:) = LV(1,:)./norm(LV(1,:)); + end + legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LV(1,1),LV(1,2),LV(1,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if exist('LU','var') + LU=unique(LU,'rows'); + for ii = 2:size(LU,1) + if flags.do_normalize + LU(ii,:) = LU(ii,:)./norm(LU(ii,:)); + end + quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LU(ii,1),LU(ii,2),LU(ii,3),0,'AutoScale','off','Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LU(ii,1),LU(ii,2),LU(ii,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LV(ii,1),LV(ii,2),LV(ii,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if flags.do_normalize + LU(1,:) = LU(1,:)./norm(LU(1,:)); + end + legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LU(1,1),LU(1,2),LU(1,3),0,'AutoScale','off','Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LU(1,1),LU(1,2),LU(1,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LV(1,1),LV(1,2),LV(1,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if exist('SV','var') + SV=unique(SV,'rows'); + % Plot ListenerView + for ii = 2:size(SV,1) + % Scale size of ListenerView vector smaller + if flags.do_normalize + SV(ii,:) = SV(ii,:)./norm(SV(ii,:)); + end + % Plot line for ListenerView vector + quiver3(SP(ii,1),SP(ii,2),SP(ii,3),SV(ii,1),SV(ii,2),SV(ii,3),0,... + 'AutoScale','off',... + 'Color',[0 0 1],'MarkerFaceColor',[0 0 1]); + end + if flags.do_normalize + SV(1,:) = SV(1,:)./norm(SV(1,:)); + end + legendEntries(end+1) = quiver3(SP(1,1),SP(1,2),SP(1,3),SV(1,1),SV(1,2),SV(1,3),0,... + 'AutoScale','off',... + 'Color',[0 0 1],'MarkerFaceColor',[0 0 1]); + end + if exist('SU','var') + SU=unique(SU,'rows'); + for ii = 2:size(SU,1) + if flags.do_normalize + SU(ii,:) = SU(ii,:)./norm(SU(ii,:)); + end + quiver3(SP(ii,1),SP(ii,2),SP(ii,3),SU(ii,1),SU(ii,2),SU(ii,3),0,... + 'AutoScale','off',... + 'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); + end + if flags.do_normalize + SU(1,:) = SU(1,:)./norm(SU(1,:)); + end + legendEntries(end+1) = quiver3(SP(1,1),SP(1,2),SP(1,3),SU(1,1),SU(1,2),SU(1,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); + end + % create legend + legendDescription = {'ListenerPosition'}; + if (strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics')) + legendDescription{end+1} = ['Receiver (order: ', num2str(S_R) ,')']; + else + legendDescription{end+1} = 'ReceiverPosition'; + end + legendDescription{end+1} ='SourcePosition'; + if (strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics')) + legendDescription{end+1} = ['Emitter (order: ', num2str(SHorder),', m: ', num2str(SHm),')']; + else + legendDescription{end+1} = 'EmitterPosition'; + end + + if exist('LV','var') + legendDescription{end+1} = 'ListenerView'; + end + if exist('LU','var') + legendDescription{end+1} = 'ListenerUp'; + end + if exist('SV','var') + legendDescription{end+1} = 'SourceView'; + end + if exist('SU','var') + legendDescription{end+1} = 'SourceUp'; + end + legend(legendEntries,legendDescription,'Location','NorthEastOutside'); + xlabel(['X / ' Obj.ListenerPosition_Units]); + ylabel(['Y / ' Obj.ListenerPosition_Units]); + zlabel(['Z / ' Obj.ListenerPosition_Units]); + + otherwise + error('This SOFAConventions is not supported for plotting'); +end + +% Set fixed aspect ratio +axis equal; +% Add a little bit extra space at the axis +axisLimits = axis(); +paddingSpace = 0.2 * max(abs(axisLimits(:))); +axisLimits([1 3]) = axisLimits([1 3]) - paddingSpace; +axisLimits([2 4]) = axisLimits([2 4]) + paddingSpace; +axis(axisLimits); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..41f96a7d3cab820f164e0ac99fbf1cbb198598ea --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m @@ -0,0 +1,506 @@ +function [M,meta,h]=SOFAplotHRTF(Obj,type,varargin) +% SOFAplotHRTF(OBJ, TYPE, R, DIR, COLOR) plots the R receiver of HRTFs given in OBJ. +% The following TYPEs are supported: +% 'EtcHorizontal' energy-time curve in the horizontal plane (+/- THR) +% 'EtcMedian' energy-time curve in the median plane (+/- THR) +% 'MagHorizontal' magnitude spectra in the horizontal plane (+/- THR) +% 'MagMedian' magnitude spectra in the median plane (+/- THR) +% 'MagSpectrum' single magnitude spectrum for direction(s) DIR in COLOR +% 'MagSagittal' magnitude spectra in a sagittal plane specified by OFFSET +/- THR +% 'ITDhorizontal' interaural time delay in the horizontal plane (not +% supported in Octave) +% +% More options are available by SOFAplotHRTF(Obj,type,parameter,value) +% +% Parameters: +% 'receiver' receiver to be plotted. Default: 1 +% 'dir' fixes the positions to be plotted: +% [azi]: shows all direction for that azimuth +% [azi, ele]: shows all distances for that direction +% [azi, ele, distance]: shows only that position +% default: [0,0] +% 'offset' chooses a plane to be plotted. Default: 0 deg. +% 'thr' threshold for selecting positions around a plane. Default: 2 deg. +% 'floor' lowest amplitude shown (dB). Default: -50 dB. +% 'convert' convert to TF domain. Function should automatically choose if neccessary. Default: 0 if conversion is not necessary; 1 if conversion is neccessary. +% +% Additionally, 'b', 'r', 'g', etc. can be used for plotting in color +% as used by PLOT. +% +% +% Supported conventions: +% SimpleFreeFieldHRIR +% SimpleFreeFieldHRSOS +% SimpleFreeFieldHRTF +% SHFreeFieldHRTF +% some special cases of GeneralTF, GeneralTF-E. +% +% [M,meta,h]=SOFAplotHRTF... returns the matrix M and meta information about displayed in the figure. +% h is the handle of the plot. meta.idx is the index to the vectors actually plotted. +% +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: type ITDhorizontal added and updated (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: dependency on function 'npi2pi' removed (required toolbox in Matlab; in Octave not supported; outdated anyway) (08.02.2022) +% #Author: Michael Mihocic: keyvalue 'R'/'r' renamed to 'receiver' (10.05.2022) +% #Author: Michael Mihocic: 'do not convert' option enabled for SimpleFreeFieldHRTF convention; +% global title only displayed if 'Obj.GLOBAL_Title' not empty (30.05.2022) +% #Author: Michael Mihocic: plotting simplefreefieldhrtf fixed (in Octave); titles fixed when plotting magspectrum (02.06.2022) +% #Author: Michael Mihocic: plotting improved when data is available in TF format (more stable, no conversions by default); +% figure titles improved (04.07.2022) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% for backward compatibility (type as position-dependent input parameter) +if nargin == 3 && ischar(type) && isscalar(varargin{1}) +% varargin = flipud(varargin(:)); + R = varargin{1}; + flags.do_normalize=1; + dir=[0,0]; + color='b'; + thr=2; + offset=0; + noisefloor=-50; +% convert=1; more comples differing below: + + if exist('OCTAVE_VERSION','builtin') + % We're in Octave + if ismember(type,{'MagHorizontal','MagMedian','MagSpectrum','MagSagittal'}) && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) + % frequency domain input data only; for Octave the list has to be extended manually because 'contains' is not available + convert = 0; + else + convert = 1; + end + else + % We're in Matlab + if contains(lower(type),'mag') && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) + % frequency domain input data only + convert = 0; + else + convert = 1; + end + end + +else + definput.keyvals.receiver=1; + definput.keyvals.dir=[0,0]; + definput.keyvals.thr=2; + definput.keyvals.offset=0; + definput.keyvals.floor=-50; + definput.flags.color={'b','r','k','y','g','c','m'}; + definput.flags.level={'normalize','absolute'}; + definput.keyvals.convert=1; + argin=varargin; + for ii=1:length(argin) + if ischar(argin{ii}), argin{ii}=lower(argin{ii}); end + end + [flags,kv] = SOFAarghelper({'receiver','dir','thr','offset','floor'},definput,argin); + R = kv.receiver; + dir = kv.dir; + thr=kv.thr; + color = flags.color; + offset = kv.offset; + noisefloor=kv.floor; + convert=kv.convert; % force convert or not + +% if exist('OCTAVE_VERSION','builtin') +% % We're in Octave +% if ismember(type,{'MagHorizontal','MagMedian','MagSpectrum','MagSagittal'}) && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) +% % frequency domain input data only; for Octave the list has to be extended manually because 'contains' is not available +% convert=kv.convert; +% else +% convert = 1; +% end +% else +% % We're in Matlab +% if contains(lower(type),'mag') && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) +% % frequency domain input data only +% convert=kv.convert; +% else +% convert = 1; +% end +% end + +end + +meta=[]; + +if convert == 1 + %% Convert data to FIR + Obj=SOFAconvertConventions(Obj); + fs=Obj.Data.SamplingRate; + + %% check if receiver selection is possible + if R > size(Obj.Data.IR,2) + error(['Choosen receiver out of range. Only ', num2str(size(Obj.Data.IR,2)), ' receivers recorded.']) + end + titlepostfix=' (converted to IR)'; +else + %% check if receiver selection is possible + if R > size(Obj.Data.Real,2) + error(['Choosen receiver out of range. Only ', num2str(size(Obj.Data.Real,2)), ' receivers recorded.']) + end + titlepostfix=''; +end +if isfield(Obj, 'GLOBAL_Title') && isempty(Obj.GLOBAL_Title) == 0 + titleprefix = [Obj.GLOBAL_Title ': ']; +else + titleprefix = ''; +end + + +%% Convert to spherical if cartesian +if strcmp(Obj.SourcePosition_Type,'cartesian') +% % Obj2=Obj; % compare to old method (Obj2) + for ii=1:Obj.API.M + [Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)]=cart2sph(Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)); +% [Obj2.SourcePosition(ii,1),Obj2.SourcePosition(ii,2),Obj2.SourcePosition(ii,3)]=cart2sph(Obj2.SourcePosition(ii,1),Obj2.SourcePosition(ii,2),Obj2.SourcePosition(ii,3)); + Obj.SourcePosition(ii,2)=rad2deg(Obj.SourcePosition(ii,2)); +% Obj2.SourcePosition(ii,2)=rad2deg(Obj2.SourcePosition(ii,2)); + Obj.SourcePosition(ii,1)=rad2deg(Obj.SourcePosition(ii,1)); +% Obj2.SourcePosition(ii,1)=rad2deg(Obj2.SourcePosition(ii,1)); + Obj.SourcePosition(ii,1)=mywrapTo180(Obj.SourcePosition(ii,1)); +% Obj2.SourcePosition(ii,1)=npi2pi(Obj2.SourcePosition(ii,1),'degrees'); % requires Mapping toolbox in Matlab + end + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degrees'; +end + +%% Plot according to the type +switch lower(type) + % Energy-time curve (ETC) in the horizontal plane + case 'etchorizontal' + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,R,:))); + pos=Obj.SourcePosition; + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,R)); + meta.idx=idx; + M2=noisefloor*ones(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + [azi,i]=sort(pos(:,1)); + M=M2(i,:); + if flags.do_normalize + M=M-max(max(M)); + end + M(M<=noisefloor)=noisefloor; + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.azi = azi; + h=surface(meta.time,azi,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Azimuth (deg)'); + title([titleprefix 'receiver: ' num2str(R)],'Interpreter','none'); + + % Magnitude spectrum in the horizontal plane + case 'maghorizontal' + pos=Obj.SourcePosition; % copy pos to temp. variable + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; % find horizontal plane + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); % find indices + pos=pos(idx,:); % truncate pos + meta.idx=idx; + if convert == 1 % converted + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + if flags.do_normalize + M=M-max(max(M)); % normalize + end + + M(M<noisefloor)=noisefloor; + [azi,i]=sort(pos(:,1)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.azi = azi; +% figure; + h=surface(meta.freq,azi,M(:,:)); + + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [azi,i]=sort(pos(:,1)); + M=M(i,:); +% figure; + + h=surface(Obj.N',azi,M); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Azimuth (deg)'); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magmedian' + azi=0; + pos=Obj.SourcePosition; + idx0=find(abs(pos(:,1))>90); + pos(idx0,2)=180-pos(idx0,2); + pos(idx0,1)=180-pos(idx0,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + pos=pos(idx,:); + meta.idx=idx; % PM: TODO: check if the correct index + + if convert == 1 % converted + + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + + h=surface(meta.freq,ele,M(:,:)); + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); +% figure; + h=surface(Obj.N',ele,M); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Elevation (deg)'); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magsagittal' + + [lat,pol]=sph2hor(Obj.SourcePosition(:,1),Obj.SourcePosition(:,2)); + pos=[lat pol]; + idx=find(pos(:,1)<(offset+thr) & pos(:,1)>(offset-thr)); + pos=pos(idx,:); + meta.idx=idx; + + if convert == 1 % converted + + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + h=surface(meta.freq,ele,M(:,:)); + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + h=surface(Obj.N',ele,M(:,:)); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Polar angle (deg)'); + title([titleprefix 'receiver: ' num2str(R) '; Lateral angle: ' num2str(offset) 'deg' titlepostfix],'Interpreter','none'); + + + % ETC in the median plane + case 'etcmedian' +% noisefloor=-50; + azi=0; + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,R,:))); + pos=Obj.SourcePosition; + idx0=find(abs(pos(:,1))>90); + pos(idx0,2)=180-pos(idx0,2); + pos(idx0,1)=180-pos(idx0,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + meta.idx=idx; % PM: TODO: Check if the correct index + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,R)); + M2=zeros(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + if flags.do_normalize + M=M2-max(max(M2)); + else + M = M2; + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.ele = ele; + h=surface(meta.time,ele,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Elevation (deg)'); + title([titleprefix 'receiver: ' num2str(R)],'Interpreter','none'); + + case 'magspectrum' + pos=round(Obj.SourcePosition*10)/10; + switch size(dir,2) + case 1 + aziPos = pos(:,1); + aziDir=dir(:,1); + aziComp = intersect(aziPos,aziDir,'rows'); + idx= find(ismember(aziPos,aziComp,'rows')); + case 2 + aziPos = pos(:,1); + aziDir=dir(:,1); + elePos = pos(:,2); + eleDir=dir(:,2); + aziComp = intersect(aziPos,aziDir,'rows'); + eleComp = intersect(elePos,eleDir,'rows'); + idx=find(ismember(aziPos,aziComp,'rows') & ... + ismember(elePos,eleComp,'rows')); + otherwise + aziPos = pos(:,1); + aziDir=dir(:,1); + elePos = pos(:,2); + eleDir=dir(:,2); + rPos = pos(:,3); + rDir=dir(:,3); + aziComp = intersect(aziPos,aziDir,'rows'); + eleComp = intersect(elePos,eleDir,'rows'); + rComp = intersect(rPos,rDir,'rows'); + idx=find(ismember(aziPos,aziComp,'rows') & ... + ismember(elePos,eleComp,'rows') & ismember(rPos,rComp,'rows')); + end + if isempty(idx), error('Position not found'); end + meta.idx=idx; + + if convert == 1 % convert + IR=squeeze(Obj.Data.IR(idx,R,:)); + if length(idx) > 1 + M=20*log10(abs(fft(IR')))'; + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + h=plot(0:fs/2/size(M,2):(size(M,2)-1)*fs/2/size(M,2),M); + for ii=1:length(idx) + labels{ii}=['#' num2str(idx(ii)) ': (' num2str(pos(idx(ii),1)) ', ' num2str(pos(idx(ii),2)) ')']; + end + legend(labels); + else % only one curve + hM=20*log10(abs(fft(IR))); + M=hM(1:floor(length(hM)/2)); + hold on; + h=plot(0:fs/2/length(M):(length(M)-1)*fs/2/length(M),M,color,... + 'DisplayName',['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + legend; + end + xlim([0 fs/2]); + titlepostfix=' (converted to IR)'; + else + + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + + if length(idx) > 1 + h=plot(Obj.N',M); + for ii=1:length(idx) + labels{ii}=['#' num2str(idx(ii)) ': (' num2str(pos(idx(ii),1)) ', ' num2str(pos(idx(ii),2)) ')']; + end + legend(labels); + else + hold on; + h=plot(Obj.N',M,color,... + 'DisplayName',['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + legend; + end + titlepostfix=''; + end + ylabel('Magnitude (dB)'); + xlabel('Frequency (Hz)'); + ylim([max(max(M))+noisefloor-10 max(max(M))+10]); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Interaural time delay in the horizontal plane + case 'itdhorizontal' + + if exist('OCTAVE_VERSION','builtin') + warning('Command ''polarplot'' not supported by Octave (yet)!') + else + [itd, ~] = SOFAcalculateITD(Obj, 'time'); + pos = Obj.SourcePosition; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); + itd = itd(idx); + meta.idx=idx; + [pos, idx_sort] = sort(pos(idx,1)); + itd = itd(idx_sort); + angles = deg2rad(pos); + %figure('Renderer', 'painters', 'Position', [10 10 700 450]); + polarplot(angles, itd, 'linewidth', 1.2); + ax = gca; + ax.ThetaDir = 'counterclockwise'; + ax.ThetaZeroLocation = 'top'; + rticks([max(itd)*2/3, max(itd)]); + rticklabels({[num2str(round(max(itd)*2/3*1e6,1)) ' ' char(181) 's'],... + [num2str(round(max(itd)*1e6,1)) ' ' char(181) 's']}); + thetaticks(0:30:330) + thetaticklabels({'0�', '30�', '60�', '90�', '120�', '150�', '180�', ... + '210�', '240�','270�', '300�', '330�'}); + grid on; + end + + otherwise + error([type , ' no supported plotting type.']) +end + + +% function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +% if rem(N,2)==0 +% f=[c; flipud(conj(c(2:end-1,:)))]; +% else +% f=[c; flipud(conj(c(2:end,:)))]; +% end +% f=real(ifft(f,N,1)); +% end + +function newangle = mywrapTo180(angle) + % transfer to range -180:180 + newangle = mod(angle+360, 360); + if newangle > 180 + newangle = newangle-360; + end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..f34eb4981fe97bd882ed2beb59e3eed0d205eb83 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m @@ -0,0 +1,32 @@ +function Obj = SOFAremoveVariable(Obj,Name) +%SOFAremoveVariable +% Obj = SOFAremoveVariable(Obj,Name) removes the user-defined variable +% from the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). +% +% + +% #Author: Piotr Majdak: adapted from SOFAaddVariable (19.06.2019) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAremoveVariable +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +switch Name + case {'API','PRIVATE','GLOBAL','PRIVATE','Data'} + error('This variable name is reserved.'); + otherwise + if isfield(Obj,Name) + Obj=rmfield(Obj,Name); + if isfield(Obj.API.Dimensions,Name) + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,Name); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..5773030f605cdbd2595fdf0635ccd146f2f66dd5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m @@ -0,0 +1,96 @@ +function [Obj] = SOFAsave(filename,Obj,varargin) +%SOFASAVE +% [Obj] = SOFAsave(filename,Obj,Compression) creates a new SOFA file and +% writes an entire data set to it. +% +% filename specifies the name of the SOFA file to which the data is written. +% Obj is a struct containing the data and meta +% data to be written to the SOFA file (see below for exact format). +% Compression is an optional numeric value between 0 and 9 specifying the +% amount of compression to be applied to the data when writing to the netCDF file. +% 0 is no compression and 9 is the most compression. +% +% The existence of mandatory variables will be checked. The dimensions +% will be updated. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc and header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAsave +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Def = SOFAdefinitions; + +%% check file name +filename=SOFAcheckFilename(filename); + +%% Remove private data +if isfield(Obj,'PRIVATE'), Obj=rmfield(Obj,'PRIVATE'); end + +%% Check convention: mandatory variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + +varNames = fieldnames(ObjCheck); +for ii=1:size(varNames,1); + if ~isfield(Obj,varNames{ii}) + error(['Mandatory variable/attribute not existing: ' varNames{ii}]); + end +end + +%% Get & set dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Check convention: read-only variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'r'); +varNames = fieldnames(ObjCheck); + +for ii=1:size(varNames,1); + if ischar(Obj.(varNames{ii})) + if ~strcmp(Obj.(varNames{ii}), ObjCheck.(varNames{ii})) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset from ' Obj.(varNames{ii}) ' to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + else + if Obj.(varNames{ii}) ~= ObjCheck.(varNames{ii}) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset from ' Obj.(varNames{ii}) ' to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + end +end + +%% check attributes (syntax, 1-dimensional string) +varNames = fieldnames(Obj); +for ii=1:size(varNames,1); + + if size(strfind(varNames{ii},'_'),2) == 1 + if ~ischar(Obj.(varNames{ii})) + error(['Attribute not a valid string: ' varNames{ii} ' = ' num2str(Obj.(varNames{ii}))]); + end + elseif size(strfind(varNames{ii},'_'),2) > 1 + error(['Attribute not valid (only one underscore "_" is allowed in attribute name): ' varNames{ii}]); + end + +end + +%% check varargin (compression) +if ~isempty(varargin) && isnumeric(varargin{1}) + if isscalar(varargin{1}) && varargin{1}>=0 && varargin{1}<=9 + Compression = varargin{1}; + else + error('Error: Compression must be a numeric scalar value between 0 and 9.'); + end +else + Compression = 1; % default +end + +%% Set/modify time information +Obj.GLOBAL_DateModified=datestr(now,Def.dateFormat); +if isempty(Obj.GLOBAL_DateCreated), Obj.GLOBAL_DateCreated=Obj.GLOBAL_DateModified; end + +%% Save file +NETCDFsave(filename,Obj,Compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..f4d978d1a0b0d4cb7721b2bf3fa8137e10f13d0e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m @@ -0,0 +1,112 @@ +function [out, azi, ele, idx] = SOFAspat(in,Obj,azi,ele) +% SOFAspat +% [out, azi, ele, idx] = SOFAspat(in, Obj, azi, ele) spatializes the sound IN using +% the HRTFs from OBJ according to the trajectory given in AZI and ELE. +% Input: +% in: vector with the sound +% Obj: SOFA object containing the HRTFs +% azi, ele: vectors with the trajectory (in degrees) independent for +% azimuth and elevation +% +% Output: +% out: binaural signal +% azi, ele: azimuth and elevation of the actual trajectory (degrees) +% idx: index of the filters (corresponds to AZI and ELE) +% +% This is an example of how to use SOFA. +% + +% #Author: Piotr Majdak (2013) +% #Author: Robert Baumgartner: adaptions (2016) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define required parameters +hop=0.5; % the hop size for the time-variant filtering (in fraction of the filter length) + +%% Initial checks +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + error('HRTFs must be saved in the SOFA conventions SimpleFreeFieldHRIR'); +end +if min(azi)<0, % Check for the required coordinate system + Obj.SourcePosition(:,1)=sph2nav(Obj.SourcePosition(:,1)); % if negative azimuths are required, swith to -90/+90 system +end +N=Obj.API.N; + +%% resize the input signal to be integer multiple of HRIR +L=length(in); +in=[in; zeros(N-mod(L,N),1)]; +L=length(in); % correct length of the input signal +S=L/N/hop; % number of segments to filter + +%% Resample the trajectory +if length(azi)>1, + azi= interp1(0:1/(length(azi)-1):1,azi,0:1/(S-1):1); +else + azi=repmat(azi,1,S); +end; +if length(ele)>1, + ele= interp1(0:1/(length(ele)-1):1,ele,0:1/(S-1):1); +else + ele=repmat(ele,1,S); +end; + +%% create a 2D-grid with nearest positions of the moving source +idx=zeros(S,1); +[target.x,target.y,target.z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(1,S)); +[pos.x,pos.y,pos.z] = sph2cart(deg2rad(Obj.SourcePosition(:,1)),... + deg2rad(Obj.SourcePosition(:,2)),Obj.SourcePosition(:,3)); +for ii=1:S % find nearest point on grid (LSP) + dist = (pos.x-target.x(ii)).^2 + (pos.y-target.y(ii)).^2 + (pos.z-target.z(ii)).^2; + [~,idx(ii)]=min(dist); +end + +%% normalize HRTFs to the frontal, eye-level position +% ii=find(Obj.SourcePosition(:,1)==0 & Obj.SourcePosition(:,2)==0); % search for position 0�/0� +% if isempty(ii) +% peak=max([sqrt(sum(Obj.Data.IR(:,1,:).*Obj.Data.IR(:,1,:))) sqrt(sum(Obj.Data.IR(:,2,:).*Obj.Data.IR(:,2,:)))]); % not found - normalize to IR with most energy +% else +% peak=([sqrt(sum(Obj.Data.IR(ii,1,:).*Obj.Data.IR(ii,1,:))) sqrt(sum(Obj.Data.IR(ii,2,:).*Obj.Data.IR(ii,2,:)))]); % found - normalize to this position +% end + +%% Spatialize +out=zeros(L+N/hop,2); +window=hanning(N); +ii=0; +jj=1; +iiend=L-N; +while ii<iiend + segT=in(ii+1:ii+N).*window; % segment in time domain + segF=fft(segT,2*N); % segment in frequency domain with zero padding + %----------- + segFO(:,1)=squeeze(fft(Obj.Data.IR(idx(jj),1,:),2*N)).*segF; + segFO(:,2)=squeeze(fft(Obj.Data.IR(idx(jj),2,:),2*N)).*segF; + %----------- + segTO=real(ifft(segFO)); % back to the time domain + out(ii+1:ii+2*N,:)=out(ii+1:ii+2*N,:)+segTO; % overlap and add + ii=ii+N*hop; + jj=jj+1; +end + +%% Normalize +% out(:,1)=out(:,1)/peak(1); +% out(:,2)=out(:,2)/peak(2); + +%% Output +% actually used angles +azi = Obj.SourcePosition(idx,1); +ele = Obj.SourcePosition(idx,2); +% upsampled for each sample +idup = floor(1:1/(N*hop):S+1-1/(N*hop)); +azi = azi(idup); +ele = ele(idup); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m new file mode 100644 index 0000000000000000000000000000000000000000..01a69bfdc557f701583d55931e79823eaec43f1f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m @@ -0,0 +1,117 @@ +function SOFAstart(flags) +% SOFAstart +% +% SOFAstart adds all needed pathes and checks if we need the Matlab or Octave +% version of the API +% +% SOFAstart(0) or SOFAstart('silent') will suppress any message during the start. +% SOFAstart ('short') will show a short header only during the start. +% SOFAstart ('full') will show all information, including all compiled +% conventions & versions. +% +% SOFAstart checks if SOFA has been started within the MATLAB session. If +% it is the case, SOFAstart skips all the initialization. If the initialization +% is required, SOFAstart('restart') performs the initialization in any case. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: 'full' flag added, changed order of display output messages (11.11.2021) +% #Author: Michael Mihocic: bug fixed when adding paths (29.11.2021) +% +% SOFA Toolbox - function SOFAstart +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Input parameters +verbose = 2; +restart = 0; +if nargin>0 + if strcmpi(flags,'silent'), verbose=0; end + if strcmpi(flags,'short'), verbose=1; end + if strcmpi(flags,'full'), verbose=3; end + if isnumeric(flags), if flags==0, verbose=0; end; end + if strcmpi(flags,'restart'), restart=1; end +end + +%% do not start when already started but not forced to restart +persistent started +if ~isempty(started) && ~restart + return; +end +started=1; +%% Check required support +if exist('OCTAVE_VERSION','builtin') + % We're in Octave + if compare_versions(OCTAVE_VERSION,'3.6.0','<=') % check if the octave version is high enough + error('You need Octave >=3.6.0 to work with SOFA.'); + end + pkg load netcdf + if ~which('test_netcdf') % check if octcdf is installed + error('You have to install the netcdf package in Octave to work with SOFA.'); + end +else + % We're in Matlab + if verLessThan('matlab','8') + warning('SOFA:start','SOFA for Matlab version <= 8 (2012b) not tested. Use on your risk.'); + end +end + + +%% Add Paths +% Get the basepath as the directory this function resides in. +% The 'which' solution below is more portable than 'mfilename' +% becase old versions of Matlab does not have "mfilename('fullpath')" +basepath=which('SOFAstart'); +basepath=basepath(1:end-12); % Kill the function name from the path. +f=filesep; + +% Add the base path and the needed sub-directories +% (basepath is added in case user navigated to this folder and changes dir) +if exist('addpath','file') || exist('addpath','builtin') % in Matlab it is a 'file'; in Octave it is a 'built-in' function + addpath(basepath,[basepath f 'helpers'],[basepath f 'coordinates'],[basepath f 'converters'],[basepath f 'demos'],[basepath f 'netcdf']); +else % in case "addpath" command is not available - can this ever be the case??? + path([basepath f 'helpers'],path); + path([basepath f 'coordinates'],path); + path([basepath f 'converters'],path); + path([basepath f 'demos'],path); + path([basepath f 'netcdf'],path); + path(path,basepath); +end + + +%% Provide SOFA conventions +dispOutput = SOFAcompileConventions; +convs = SOFAgetConventions; + +%% Display general informations + +if verbose + disp(['SOFA Matlab/Octave API, version ' SOFAgetVersion '. Copyright 2013-2022 Acoustics Research Institute (piotr@majdak.com).']); + if verbose >= 3 + disp(dispOutput); + end + if verbose >= 2 + disp(['This API implements SOFA version ' SOFAgetVersion('SOFA') '.']); + text=['Available SOFA Conventions: ' convs{1}]; + for ii=2:length(convs) + text=[text ', ' convs{ii}]; + end + disp(text); + disp(['SOFAdbPath (local HRTF database): ' SOFAdbPath('reset') ]); + disp(['SOFAdbURL (internet repository): ' SOFAdbURL('reset')]); + end +end + + + +% FIXME: I would check only if the URL is available in the function where it is +% needed. At the start it takes to long. Octaves urlread didn't know the TimeOut +% parameter. +%[~,stat]=urlread(SOFAdbURL); +%if ~stat, disp(' --> could not connect'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m new file mode 100644 index 0000000000000000000000000000000000000000..5dbafdffb3fac9fa18c772584ce1d83f12090628 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m @@ -0,0 +1,181 @@ +function Obj = SOFAupdateDimensions(Obj,varargin) +%SOFAupdateDimensions +% Obj = SOFAupdateDimensions(Obj, varargin) updates the dimensions in the SOFA +% structure +% +% Obj is a struct containing the data and meta. +% The dimension sizes are created as .API.X and updated corresponding to the +% conventions +% flag is 'nodata', 'all', or 'verbose'; default is 'all' +% set 'verbose' to 1 to obtain detailed information on the check. + +% #Author: Piotr Majdak +% #Author: Piotr Majdak: String support added (09.08.2014) +% #Author: Piotr Majdak: Verbose mode added (10.10.2020) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupdateDimensions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.keyvals.Index=[]; +definput.keyvals.verbose=0; +definput.flags.type={'data','nodata'}; +[flags,kv]=SOFAarghelper({'Index'},definput,varargin); +v=kv.verbose; + +%% Get conventions with allowed dimensions +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +if v, disp(['SOFA Convention: ' Obj.GLOBAL_SOFAConventions]); end + +%% Add dimensions if required +dims=fieldnames(SOFAdefinitions('dimensions')); +for ii=1:size(dims,1) + if ~isfield(Obj.API,dims{ii}), Obj.API.(dims{ii})=0; end +end + +%% Update dimension sizes from the variables having dominant dimensions sizes + % fix dimension sizes +Obj.API.I=1; +Obj.API.C=3; + % check all metadata variables for dominant dimension sizes +dims='renm'; +f=fieldnames(rmfield(OC.API.Dimensions,'Data')); +for ii=1:length(dims) + for jj=1:length(f) + dim=strfind(OC.API.Dimensions.(f{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(f{jj}),dim(1)); + if (v), disp([upper(dims(ii)) ' set to ' num2str(size(Obj.(f{jj}),dim(1))) ' that is the #' num2str(dim(1)) ' dimension of ' f{jj}]); end + break; + end + end +end +% check all data variables +if flags.do_data + fd=fieldnames(OC.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fd) + dim=strfind(OC.API.Dimensions.Data.(fd{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fd{jj}),dim(1)); + if (v), disp([upper(dims(ii)) ' set to ' num2str(size(Obj.Data.(fd{jj}),dim(1))) ' that is the #' num2str(dim(1)) ' dimension of Data.' fd{jj}]); end + break; + end + end + end +end + +%% Update the dimensions of metadata variables +Smax=0; +X=rmfield(Obj,{'Data','API'}); +if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end +Xf=fieldnames(X); +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions, Xf{ii}), % is a known variable + dim=OC.API.Dimensions.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.(Xf{ii})=dim; + if v, disp([Xf{ii} ': convention variable, used dimension: ' dim]); end; + end + else % is a user-defined variable + if ~isfield(Obj.API.Dimensions,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without dimension provided in API.Dimensions.']); + else + dim=Obj.API.Dimensions.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension does not match.']); + else + if v, disp([Xf{ii} ': user-defined variable, used dimension: ' dim]); end; + end + end + end + Smax=max(Smax,S); + end +end +%% Update the dimensions of data variables +if flags.do_data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions.Data, Xf{ii}), % is a known variable + dim=OC.API.Dimensions.Data.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.Data.(Xf{ii})=dim; + if v, disp(['Data.' Xf{ii} ': convention variable, used dimension: ' dim]); end; + end + Smax=max(Smax,S); + else + if ~isfield(Obj.API.Dimensions.Data,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without a dimension.']); + else + dim=Obj.API.Dimensions.Data.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension does not match.']); + else + if v, disp(['Data.' Xf{ii} ': user-defined variable, used dimension: ' dim]); end; + end + end + end + end + end +end +%% Update the size of the longest string +if Smax>0, + Obj.API.S=Smax; + if v, disp(['S set to ' num2str(Obj.API.S)]); end +else + if v, disp('S unused (set to 0)'); end +end + +%% Return the size of x. If x is a cell, return the size of the strings in x. +function s=sizecell(x,dim) +if iscell(x) + s=size(char(x)); + if size(x,1)~=s(1) s=[size(x) s(2)]; end % multidim cellarays: s = [celldim1, celldim2, ... , celldimN, stringdim] +else + s=size(x); +end + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.(f)),upper(str)); + +%% dims is a cell array with allowed dimensions. +% S is the size of the string dimension. S=0 when S does not exist +% dimA is a vector with the actual dimensions. +% dim is a string with the matching dimension +function [dim,S]=checkdim(Obj,dims,dimA) +dim=[]; S=0; +for jj=1:length(dims) + dimS=dims{jj}; + if length(dimS)==1, dimS=[dimS 'I']; end; % 1D required, but Matlab is always 2D at least. + dimR=getdim(Obj.API,dimS); + if length(dimA)==length(dimR), % the same size? + if ~isempty(strfind(dimS,'S')) + Sidx=strfind(dimS,'S'); + S=max(S,dimA(Sidx)); + dimR(Sidx)=dimA(Sidx); % string dim are always correct + end + if dimA==dimR, dim=upper(dims{jj}); break; end; % found! + elseif length(dimA)<length(dimR) % extend the size? + if [dimA ones(1,length(dimR)-length(dimA))]==dimR, dim=upper(dims{jj}); break; end; % found! + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..e1acb20158d187b75073a274e0486ee86444ab10 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m @@ -0,0 +1,174 @@ +function [Obj,modified] = SOFAupgradeConventions(Obj) +%SOFAcompatibility +% [Obj,modified] = SOFAupgradeConventions(Obj) upgrades the Obj to the next higher +% version if required. MODIFIED is 1 when an upgrade was required. +% In order to obtain the most recent version, SOFAupgradeConventions +% should be processed recursively until MODIFIED is 0. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupgradeConventions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +modified=0; + +%% Upgrade specific to a SOFA version + +switch Obj.GLOBAL_Version, + case '0.3' + modified=1; + % in SOFA 0.3, only SimpleFreeFieldHRIR 0.1 was supported. + % Updating SimpleFreeFieldHRIR 0.1 to 0.2 + Obj.GLOBAL_Version='0.4'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + Obj.GLOBAL_TimeCreated=Obj.GLOBAL_DatabaseTimeCreated; + Obj.GLOBAL_TimeModified=Obj.GLOBAL_DatabaseTimeModified; + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.3'); + % remove dimensional variables and not used variables/attributes + dims={'I','R','E','N','M','C','Q','SourceView',... + 'SourceUp','GLOBAL_DatabaseTimeCreated','GLOBAL_DatabaseTimeModified'}; + f=fieldnames(Obj); + for ii=1:length(dims) + for jj=1:length(f) + if strcmp(f{jj},dims{ii}), + Obj=rmfield(Obj,f{jj}); % remove variable or attribute + if isempty(strfind(f{jj},'_')), + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,f{jj}); % remove dimension + end + elseif strcmp(f{jj}(1:min(length(dims{ii})+1,length(f{jj}))),[dims{ii} '_']) + Obj=rmfield(Obj,f{jj}); % remove attributes of that variable + end + end + end + warning('SOFA:upgrade','SOFA 0.3 upgraded to 0.4. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.4' + % in SOFA 0.4, only SimpleFreeFieldHRIR might need upgrade + if strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + switch Obj.GLOBAL_SOFAConventionsVersion + case '0.2' + % Upgrade from SimpleFreeFieldHRIR 0.2 to 0.3 + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SimpleFreeFieldHRIR 0.2'); + % Create temp SourcePosition + azi=bsxfun(@times,Obj.ListenerRotation(:,1),ones(size(Obj.ListenerPosition,1),1)); + ele=bsxfun(@times,Obj.ListenerRotation(:,2),ones(size(Obj.ListenerPosition,1),1)); + r=bsxfun(@times,Obj.ListenerPosition(:,1),ones(size(Obj.ListenerRotation,1),1)); + % Copy ListenerPosition + Obj.ListenerPosition=Obj.SourcePosition; + % Overwrite SourcePosition + Obj.SourcePosition=[azi ele r]; + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degree, degree, meter'; + % Mirror the ListenerView and correct ListenerUp + Obj.ListenerView=-Obj.ListenerView; + Obj.ListenerUp=[0 0 1]; + % Remove irrelevant fields + if isfield(Obj,'SourceView'); Obj=rmfield(Obj,'SourceView'); end + if isfield(Obj,'SourceView_Type'); Obj=rmfield(Obj,'SourceView_Type'); end + if isfield(Obj,'SourceView_Units'); Obj=rmfield(Obj,'SourceView_Units'); end + if isfield(Obj,'SourceUp'); Obj=rmfield(Obj,'SourceUp'); end + if isfield(Obj,'SourceUp_Type'); Obj=rmfield(Obj,'SourceUp_Type'); end + if isfield(Obj,'SourceUp_Units'); Obj=rmfield(Obj,'SourceUp_Units'); end + Obj=rmfield(Obj,'ListenerRotation'); + Obj=rmfield(Obj,'ListenerRotation_Type'); + Obj=rmfield(Obj,'ListenerRotation_Units'); + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,'ListenerRotation'); + Obj.GLOBAL_SOFAConventionsVersion='0.3'; + end + end + modified=1; + Obj.GLOBAL_Version='0.5'; + warning('SOFA:upgrade','SOFA 0.4 upgraded to 0.5. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.5' + % Upgrade from 0.5 to 0.6 + Obj.GLOBAL_DateCreated=Obj.GLOBAL_TimeCreated; + Obj=rmfield(Obj,'GLOBAL_TimeCreated'); + Obj.GLOBAL_DateModified=Obj.GLOBAL_TimeModified; + Obj=rmfield(Obj,'GLOBAL_TimeModified'); + Obj.GLOBAL_Origin=Obj.GLOBAL_Source; + Obj=rmfield(Obj,'GLOBAL_Source'); + if isfield(Obj,'ListenerView') && ~isfield(Obj,'ListenerView_Type') + Obj.ListenerView_Type = 'cartesian'; + Obj.ListenerView_Units = 'meter'; + end + if isfield(Obj,'ReceiverView') && ~isfield(Obj,'ReceiverView_Type') + Obj.ReceiverView_Type = 'cartesian'; + Obj.ReceiverView_Units = 'meter'; + end + if isfield(Obj,'GLOBAL_SubjectID'), + Obj.GLOBAL_ListenerShortName=Obj.GLOBAL_SubjectID; % rename SubjectID to ListenerShortName + Obj=rmfield(Obj,'GLOBAL_SubjectID'); + end + switch Obj.GLOBAL_SOFAConventions + case {'SimpleFreeFieldHRIR', 'SimpleFreeFieldTF'} + Obj.GLOBAL_SOFAConventionsVersion='0.4'; + case {'GeneralFIR', 'GeneralTF', 'SingleRoomDRIR'} + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + end + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.5'); + Obj.GLOBAL_Version='0.6'; + modified=1; + warning('SOFA:upgrade','SOFA 0.5 upgraded to 0.6. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.6' + X=SOFAgetConventions(Obj.GLOBAL_SOFAConventions); + if ~isempty(X), + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.6'); + Obj.GLOBAL_Version='1.0'; + Obj.GLOBAL_SOFAConventionsVersion = X.GLOBAL_SOFAConventionsVersion; + % replace aliases by correct unit names + U=SOFAdefinitions('units'); + Uf=fieldnames(U); + f=fieldnames(Obj); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.(f{jj})=regexprep(Obj.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + f=fieldnames(Obj.Data); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.Data.(f{jj})=regexprep(Obj.Data.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + modified=1; + warning('SOFA:upgrade','SOFA 0.6 upgraded to 1.0. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + else + warning('SOFA:upgrade','Unknown conventions'); + end +end + +%% Upgrade specific to conventions +if ~modified + switch Obj.GLOBAL_SOFAConventions + case 'MultiSpeakerBRIR' + if strcmp(Obj.GLOBAL_SOFAConventionsVersion,'0.1'); + % upgrade to 0.2 + Obj.GLOBAL_DataType='FIRE'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + %Obj.Data.Delay = + if strcmp(Obj.API.Dimensions.Data.Delay,'IR') + Obj.API.Dimensions.Data.Delay='IRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + if strcmp(Obj.API.Dimensions.Data.Delay,'MR') + Obj.API.Dimensions.Data.Delay='MRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + modified=1; + warning('SOFA:upgrade','Conventions MultiSpeakerBRIR 0.1 upgraded to 0.2. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..fa39ddb4772064bfa0d9f27259c256aff14605f9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv @@ -0,0 +1,58 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldDirectivityTF rm attribute This conventions stores directivities of acoustic sources (instruments, loudspeakers, singers, talkers, etc) in the frequency domain for multiple musical notes in free field. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:RoomType free field m attribute The room information can be arbitrary, but the spatial setup assumes free field. +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment m attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data +GLOBAL:Musician attribute Narrative description of the musician such as position, behavior, or personal data if not data-protected, e.g., 'Christiane Schmidt sitting on the chair', or 'artificial excitation by R2D2'. +GLOBAL:Description attribute Narrative description of a measurement. For musical instruments/singers, the note (C1, D1, etc) or the dynamic (pp., ff., etc), or the string played, the playing style (pizzicato, legato, etc.), or the type of excitation (e.g., hit location of a cymbal). For loudspeakers, the system and driver units. +GLOBAL:SourceType m attribute Narrative description of the acoustic source, e.g., 'Violin', 'Female singer', or '2-way loudspeaker' +GLOBAL:SourceManufacturer m attribute Narrative description of the manufacturer of the source, e.g., 'Stradivari, Lady Blunt, 1721' or 'LoudspeakerCompany' +ListenerPosition [0 0 0] m IC, MC double Position of the microphone array during the measurements. +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double Orientation of the microphone array +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +ListenerUp [0 0 1] m IC, MC double Up vector of the microphone array +ReceiverPosition [0 0 1] m IC, RC, RCM double Positions of the microphones during the measurements (relative to the Listener) +ReceiverPosition:Type spherical m attribute +ReceiverPosition:Units degree, degree, metre m attribute +SourcePosition [0 0 0] m IC, MC double Position of the acoustic source (instrument) +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourcePosition:Reference m attribute Narrative description of the spatial reference of the source position, e.g., for the trumpet, 'The bell'. Mandatory in order to provide a reference across different instruments +SourceView [1 0 0] m IC, MC double Orientation of the acoustic source (instrument) +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +SourceView:Reference m attribute Narrative description of the spatial reference of the source view, e.g., for the trumpet, 'Viewing direction of the bell'. Mandatory in order to provide a reference across different instruments +SourceUp [0 0 1] m IC, MC double Up vector of the acoustic source (instrument) +SourceUp:Reference m attribute Narrative description of the spatial reference of the source up, e.g., for the trumpet, 'Along the keys, keys up'. Mandatory in order to provide a reference across different instruments +EmitterPosition [0 0 0] m IC, MC double A more detailed structure of the Source. In a simple settings, a single Emitter is considered that is collocated with the source. +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterDescription {''} IS, MS string A more detailed structure of the source. In a simple setting, a single Emitter is considered that is collocated with the source. In a more complicated setting, this may be the strings of a violin or the units of a loudspeaker. +MIDINote 0 I, M double Defines the note played by the source during the measurement. The note is specified a MIDI note by the [https://www.midi.org/specifications-old/item/the-midi-1-0-specification MIDI specifications, version 1.0]. Not mandatory, but recommended for tonal instruments. +Description {''} MS string This variable is used when the description varies with M. +SourceTuningFrequency 440 I, M double Frequency (in hertz) to which a musical instrument is tuned to corresponding to the note A4 (MIDINote=69). Recommended for tonal instruments. +Data.Real 0 m MRN double Real part of the complex spectrum. The default value 0 indicates that all data fields are initialized with zero values. +Data.Imag 0 m MRN double Imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Units used for N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.1.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.1.csv new file mode 100644 index 0000000000000000000000000000000000000000..08f0f7cf7721f6b734155d8bf122b88a615bf567 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.1.csv @@ -0,0 +1,59 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldDirectivityTF rm attribute This conventions stores directivities of acoustic sources (instruments, loudspeakers, singers, talkers, etc) in the frequency domain for multiple musical notes in free field. +GLOBAL:SOFAConventionsVersion 1.1 rm attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:RoomType free field m attribute The room information can be arbitrary, but the spatial setup assumes free field. +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data +GLOBAL:Musician attribute Narrative description of the musician such as position, behavior, or personal data if not data-protected, e.g., 'Christiane Schmidt sitting on the chair', or 'artificial excitation by R2D2'. +GLOBAL:Description attribute Narrative description of a measurement. For musical instruments/singers, the note (C1, D1, etc) or the dynamic (pp., ff., etc), or the string played, the playing style (pizzicato, legato, etc.), or the type of excitation (e.g., hit location of a cymbal). For loudspeakers, the system and driver units. +GLOBAL:SourceType m attribute Narrative description of the acoustic source, e.g., 'Violin', 'Female singer', or '2-way loudspeaker' +GLOBAL:SourceManufacturer m attribute Narrative description of the manufacturer of the source, e.g., 'Stradivari, Lady Blunt, 1721' or 'LoudspeakerCompany' +ListenerPosition [0 0 0] m IC, MC double Position of the microphone array during the measurements. +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double Orientation of the microphone array +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +ListenerUp [0 0 1] m IC, MC double Up vector of the microphone array +ReceiverPosition [0 0 0] m IC, RC, RCM double Positions of the microphones during the measurements (relative to the Listener) +ReceiverPosition:Type spherical m attribute Type of the coordinate system used. +ReceiverPosition:Units degree, degree, metre m attribute Units of the coordinates. +SourcePosition [0 0 0] m IC, MC double Position of the acoustic source (instrument) +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourcePosition:Reference m attribute Narrative description of the spatial reference of the source position, e.g., ‘The bell’ for a trumpet or ‘On the front plate between the low- and mid/high-frequency unit’ for a loudspeaker. Mandatory in order to provide a reference across different sources. +SourceView [1 0 0] m IC, MC double View vector for the orientation. +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +SourceView:Reference m attribute Narrative description of the spatial reference of the source view, e.g., ‘Viewing direction of the bell’ for a trumpet or 'Perpendicular to the front plate` for a loudspeaker. Mandatory in order to provide a reference across different sources. +SourceUp [0 0 1] m IC, MC double Up vector of the acoustic source (instrument) +SourceUp:Reference m attribute Narrative description of the spatial reference of the source up, e.g., ‘Along the keys, keys up’ for a trumpet or ‘Perpendicular to the top plate’ for a loudspeaker. Mandatory in order to provide a reference across different sources. +EmitterPosition [0 0 0] m EC, ECM double Position. In a simple settings, a single emitter is considered that is collocated with the source. +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterDescription {''} IS, MS string A more detailed structure of the source. In a simple setting, a single Emitter is considered that is collocated with the source. In a more complicated setting, this may be the strings of a violin or the units of a loudspeaker. +GLOBAL:EmitterDescriptions MS string A more detailed description of the Emitters. For example, this may be the strings of a violin or the units of a loudspeaker. +MIDINote 0 I, M double Defines the note played by the source during the measurement. The note is specified a MIDI note by the [https://www.midi.org/specifications-old/item/the-midi-1-0-specification MIDI specifications, version 1.0]. Not mandatory, but recommended for tonal instruments. +Description {''} MS string This variable is used when the description varies with M. +SourceTuningFrequency 440 I, M double Frequency (in hertz) to which a musical instrument is tuned to corresponding to the note A4 (MIDINote=69). Recommended for tonal instruments. +Data.Real 0 m MRN double Real part of the complex spectrum. The default value 0 indicates that all data fields are initialized with zero values. +Data.Imag 0 m MRN double Imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency attribute Optional +N:Units hertz m attribute Units used for N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..5321640181eb021ff0fc9b76d81474f30ba7477d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldHRIR rm attribute An extension of SimpleFreeFieldHRIR in order to consider more complex data sets described in spatially continuous representation. Each HRTF direction corresponds to an emitter, and a consistent measurement for a single listener and all directions is described by a set of the emitter positions surrounding the listener. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR-E rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute Short name of the listener (as for example the subject ID). +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Source position is assumed to be the ListenerPosition in order to reflect Emitters surrounding the Listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double Radius in 'spherical harmonics', Position in 'cartesian' and 'spherical' +EmitterPosition:Type spherical harmonics m attribute Can be 'spherical harmonics', 'cartesian', or 'spherical' +EmitterPosition:Units degree, degree, metre m attribute +GLOBAL:DatabaseName m attribute Name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.IR [0 0] m MRNE double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IRI, MRI, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..d7481c9ebccaa6531c7fa205b00f08b2f4d52859 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldHRTF rm attribute This conventions is for HRTFs created under conditions where room information is irrelevant and stored as SH coefficients +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF-E rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Source position is assumed to be the ListenerPosition in order to reflect Emitters surrounding the Listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double Radius in 'spherical harmonics', Position in 'cartesian' and 'spherical' +EmitterPosition:Type spherical harmonics m attribute Can be 'spherical harmonics', 'cartesian', or 'spherical' +EmitterPosition:Units degree, degree, metre m attribute +GLOBAL:DatabaseName m attribute Name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.Real [0 0] m MRNE double +Data.Imag [0 0] m MRNE double +N 0 m N double +N:LongName frequency attribute +N:Units Hertz m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..0ea2192b243e79b7337c3368cea54fe6b875f541 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR-E rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR-E rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, EC, ECM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mrne double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..c767c77a815dd871c45098f2e851e17c424cebcf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIRE rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mREn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..a3d46ef46e288224905e221d7f5381c0f6c431d2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mRn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..9845f4b14ded04145b7479f021a2c7a88fc52db2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..72f5cf8226401f1fc6057d99839241cc91bee519 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralSOS rm attribute This conventions follows GeneralFIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0], [3 1 2]); m mrn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I, M double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv new file mode 100644 index 0000000000000000000000000000000000000000..3b2668520b8202463d5ba28c21408ddb797f0415 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralString rm attribute Conventions for testing the string support +GLOBAL:SOFAConventionsVersion 0.2 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType String rm attribute We store strings here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +String2 {'' ''} m MRS string +String2:Description 2-D string m attribute +String2:Units latin1 m attribute +Data.String1 {''} m MS string +Data.String1:Description 1-D string m attribute +Data.String1:Units latin1 m attribute +Data.String2 {'' ''} m MRS string +Data.String2:Description 2-D string m attribute +Data.String2:Units latin1 m attribute +Data.Double [0 0] m mRn double +Data.Double:Units double m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..bcd48c849b46ee48330af12bd2ba5f6ae52bf09d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralTF-E rm attribute This conventions stores TFs depending in the Emiiter for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralTF +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF-E rm attribute We store frequency-dependent data depending on the emitter here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, EC, ECM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mrne double The real part of the complex spectrum +Data.Imag 0 m MRNE double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..3a14a5de1231813d3a5bab18f38ebb029084e067 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralTF rm attribute This conventions stores TFs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralFIR. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mRn double The real part of the complex spectrum +Data.Imag 0 m MRN double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..ddb04c75fd6aecebf453782881b1e6d3194eaa02 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralTF rm attribute This conventions stores TFs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralFIR. +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eC, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mrn double The real part of the complex spectrum +Data.Imag 0 m MRN double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..73696de08abd826f5eb3da8d460aef2845c1618f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv @@ -0,0 +1,61 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions General rm attribute This conventions is for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR m attribute The datatype can be arbitrary +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] IC, MC double +ListenerUp [0 0 1] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] IC, MC double +SourceUp [0 0 1] IC, MC double +SourceView:Type cartesian attribute +SourceView:Units metre attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmiiterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv new file mode 100644 index 0000000000000000000000000000000000000000..bb45db38ab7773c59b5361ca94cdb43d1b8e5122 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv @@ -0,0 +1,48 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions MultiSpeakerBRIR rm attribute This convention is for BRIRs recorded in reverberant conditions from multiple loudspeaker sources at a number of listener orientations. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:RoomDescription attribute narrative description of the room +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +EmitterUp [0 0 1] ECI, ECM double When EmitterUp provided, EmitterView must be provided as well +EmitterView [1 0 0] ECI, ECM double When EmitterView provided, EmitterUp must be provided as well +EmitterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR [1 1] m mREn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IRE, MRE double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..3307cfcbbcc50ae300ca91e98b73cd44e1a9a8d4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv @@ -0,0 +1,47 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRIR rm attribute This convention set is for HRIRs recorded under free-field conditions or other IRs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double +SourceUp [0 0 1] IC, MC double +SourceView [1 0 0] IC, MC double +SourceView:Type cartesian attribute +SourceView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..9aecc490b9896ddbc6cab3a90a8074a36721e031 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRSOS rm attribute This convention set follows SimpleFreeFieldHRIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0; 0 0 0 1 0 0], [3 1 2]); m mRn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I, M double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..327c97f1a3379634d099054873a9ca05fa79c9d7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRTF rm attribute This conventions is for HRTFs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.Real [0 0] m mRn double +Data.Imag [0 0] m MRN double +N 0 m N double +N:LongName frequency attribute +N:Units hertz m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..f576df1d3caaf1fa072d279d150326ea5798ac27 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldSOS rm attribute This convention set follows SimpleFreeFieldHRIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0; 0 0 0 1 0 0], [3 1 2]); m mRn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..a19745727c4d794d46059ed58e060ed9e3919afc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv @@ -0,0 +1,51 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleHeadphoneIR rm attribute Conventions for IRs with a 1-to-1 correspondence between emitter and receiver. The main application for this convention is to store headphone IRs recorded for each emitter and each ear. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR rm attribute We will store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute Room type is not relevant here +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Default: Headphones are located at the position of the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0.09 0; 0 -0.09 0] m eCI, eCM double Default: Reflects the correspondence of each emitter to each receiver +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double +GLOBAL:DatabaseName m attribute Correspondence to a database +GLOBAL:ListenerShortName m attribute Correspondence to a subject from the database +GLOBAL:ListenerDescription m attribute Narrative description of the listener (or mannequin) +GLOBAL:SourceDescription m attribute Narrative description of the headphones +GLOBAL:SourceManufacturer m attribute Name of the headphones manufacturer +SourceManufacturer {''} MS string Optional M-dependent version of the attribute SourceManufucturer +GLOBAL:SourceModel m attribute Name of the headphone model. Must uniquely describe the headphones of the manufacturer +SourceModel {''} MS string Optional M-dependent version of the attribute SourceModel +GLOBAL:SourceURI m attribute URI of the headphone specifications +GLOBAL:ReceiverDescription m attribute Narrative description of the microphones +ReceiverDescriptions {''} MS string R-dependent version of the attribute ReceiverDescription +GLOBAL:EmitterDescription m attribute Narrative description of the headphone drivers +EmitterDescriptions {''} MS string E-dependent version of the attribute EmitterDescription +MeasurementDate 0 M double Optional M-dependent date and time of the measurement diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv new file mode 100644 index 0000000000000000000000000000000000000000..0658a79a697550a8a25f646859395b24383df7a3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv @@ -0,0 +1,47 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SingleRoomDRIR rm attribute This convention stores arbitrary number of receivers while providing an information about the room. The main application is to store DRIRs for a single room. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute +GLOBAL:RoomDescription m attribute +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +SourceUp [0 0 1] m IC, MC double +SourceView [-1 0 0] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +Data.IR [0] m mrn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0] m IR, MR double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..7f83b04c5db8a3e21ee5474a5f3b96ccf39e6294 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv @@ -0,0 +1,77 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SingleRoomMIMOSRIR rm attribute Single-room multiple-input multiple-output spatial room impulse responses, depending on Emitters +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR-E rm attribute Shall be FIR-E +GLOBAL:RoomType shoebox m attribute Shall be 'shoebox' or 'dae' +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data. +GLOBAL:RoomShortName attribute Short name of the Room +GLOBAL:RoomDescription attribute Informal verbal description of the room +GLOBAL:RoomLocation attribute Location of the room +GLOBAL:RoomGeometry attribute URI to a file describing the room geometry. +RoomTemperature 0 I, M double Temperature during measurements +RoomTemperature:Units kelvin attribute Units of the room temperature +RoomVolume 0 I, M double Volume of the room +RoomVolume:Units cubic metre attribute Units of the room volume +RoomCornerA [0 0 0] IC, MC double +RoomCornerB [1 2 3] IC, MC double +RoomCorners 0 II double The value of this attribute is to be ignored. It only exist to for RoomCorners:Type and RoomCorners:Units +RoomCorners:Type cartesian attribute +RoomCorners:Units metre attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double +ListenerUp [0 0 1] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverDescriptions {''} RS string R-dependent version of the attribute ReceiverDescription +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type spherical m attribute Can be of any type enabling both spatially discrete and spatially continuous representations. +ReceiverPosition:Units degree, degree, metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] m IC, MC double +SourceUp [0 0 1] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterDescriptions {''} ES string E-dependent version of the attribute EmitterDescription +EmitterPosition [0 0 0] m IC, ECI, ECM double Can be of any type enabling both spatially discrete and spatially continuous representations. +EmitterPosition:Type spherical m attribute +EmitterPosition:Units degree, degree, metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmitterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR 0 m mrne double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRI, MRI, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..08abef00675f9c50d4aac3c0a552cfb67c2f1cbe --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv @@ -0,0 +1,77 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SingleRoomSRIR rm attribute For measuring SRIRs in a single room with a single excitation source (e.g., a loudspeaker) and a listener containing an arbitrary number of omnidirectional receivers (e.g., a microphone array). +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR rm attribute Shall be FIR +GLOBAL:RoomType shoebox m attribute Shall be 'shoebox' or 'dae' +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data. +GLOBAL:RoomShortName attribute Short name of the Room +GLOBAL:RoomDescription attribute Informal verbal description of the room +GLOBAL:RoomLocation attribute Location of the room +GLOBAL:RoomGeometry attribute URI to a file describing the room geometry. +RoomTemperature 0 I, M double Temperature during measurements +RoomTemperature:Units kelvin attribute Units of the room temperature +RoomVolume 0 I, M double Volume of the room +RoomVolume:Units cubic metre attribute Units of the room volume +RoomCornerA [0 0 0] IC, MC double +RoomCornerB [1 2 3] IC, MC double +RoomCorners 0 II double The value of this attribute is to be ignored. It only exist to for RoomCorners:Type and RoomCorners:Units +RoomCorners:Type cartesian attribute +RoomCorners:Units metre attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double +ListenerUp [0 0 1] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverDescriptions {''} RS string R-dependent version of the attribute ReceiverDescription +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type spherical m attribute Can be of any type enabling both spatially discrete and spatially continuous representations. +ReceiverPosition:Units degree, degree, metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] m IC, MC double +SourceUp [0 0 1] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterDescriptions {''} ES string E-dependent version of the attribute EmitterDescription +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type spherical m attribute Shall be 'cartesian' or 'spherical', restricting to spatially discrete emitters. +EmitterPosition:Units degree, degree, metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmitterView:Type cartesian attribute Shall be 'cartesian' or 'spherical', restricting to spatially discrete emitters. +EmitterView:Units metre attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..3d885d7c8b34b5aa62ded535f12efa619d8c6f97 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m @@ -0,0 +1,49 @@ +function Obj=SOFAconvertARI2SOFA(hM,meta,stimPar) +% OBJ=SOFAconvertARI2SOFA(hM,meta,stimPar) converts the HRTFs described in hM, meta, and +% stimPar (see ARI HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(hM,1); % hM is [N M R], data.IR must be [M R N] +Obj.Data.SamplingRate = stimPar.SamplingRate; + +%% Fill with attributes +if isfield(stimPar, 'SubjectID'), Obj.GLOBAL_ListenerShortName = stimPar.SubjectID; end +if isfield(stimPar,'Application') + if isfield(stimPar.Application,'Name'), Obj.GLOBAL_ApplicationName = stimPar.Application.Name; end + if isfield(stimPar.Application,'Version'), Obj.GLOBAL_ApplicationVersion = stimPar.Application.Version; end +end + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.2 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) zeros(size(hM,2),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) 1.2*ones(size(hM,2),1)]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with some additional data +Obj.GLOBAL_History='Converted from the ARI format'; +if size(meta.pos,2)>2, Obj=SOFAaddVariable(Obj,'MeasurementSourceAudioChannel','M',meta.pos(1:size(hM,2),3)); end +if isfield(meta,'lat'), Obj=SOFAaddVariable(Obj,'MeasurementAudioLatency','MR',meta.lat); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8e8eee834f3eecbf5cf0586460bce52910c01df4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m @@ -0,0 +1,83 @@ +function Obj = SOFAconvertBTDEI2SOFA(BTDEI) +% OBJ=SOFAconvertBTDEI2SOFA(BTDEI) converts the HRTFs described in BT-DEI +% to a SOFA object. +% +% BTDEI format is used by Michele Geronazzo, University of Padova. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% get empty object (the flag 'm' provides the mandatory fields only) +Obj=SOFAgetConventions('SimpleHeadphoneIR','m'); + +Obj.GLOBAL_Title = 'HPIR'; +Obj.GLOBAL_DatabaseName = BTDEI.specs.Database; + +Obj.GLOBAL_History = 'Converted from the BT-DEI format'; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HpTFs from DEI - University of Padova'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_AuthorContact = 'geronazzo@dei.unipd.it'; +Obj.GLOBAL_References = ['M. Geronazzo, F. Granza, S. Spagnol, F. Avanzini. ', ... + 'A Standardized Repository of Head-Related and Headphone Impulse Response Data ', ... + 'In 134th Convention of the Audio Engineering Society, May 2013.']; +Obj.GLOBAL_Organization = 'Department of Information Engineering, University of Padova'; +Obj.GLOBAL_Comment = ''; + +% copy the data + +% Emitter - Source +Obj.GLOBAL_SourceDescription = [BTDEI.hp.Id ' - ' BTDEI.hp.Producer ' ' BTDEI.hp.Model]; +Obj.GLOBAL_SourceManufacturer = BTDEI.hp.Producer; +Obj.GLOBAL_SourceModel = BTDEI.hp.Model; +%Obj.GLOBAL_SourceURI = BTDEI.hp.Uri; +% Receiver - Listener +Obj.GLOBAL_SubjectID = BTDEI.specs.SubjectId; +Obj.GLOBAL_ListenerDescription = BTDEI.sbjType; +Obj.GLOBAL_ReceiverDescription = BTDEI.specs.MicrophonePosition; % qualitative data e.g. blocked ear canal, open ear canal, at the eardrum + + +Obj.ListenerPosition = [0 0 0]; +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 0]; +Obj.SourcePosition = [0 0 0]; +Obj.EmitterPosition = [0 0.09 0; 0 -0.09 0]; + +%% Fill data with data +Obj.Data.SamplingRate = BTDEI.specs.SampleRate; % Sampling rate + +% calculate the effective size of the data matrix +M = length(BTDEI.data); % number of repositionings +R = size(BTDEI.data(1).HpIR,2); % number of channels (stereo) + +len_vec = zeros(M,1); +for ii=1:M + len_vec(ii)= length(BTDEI.data(ii).HpIR); +end +N = max(len_vec); + +Obj.API.M=M; +Obj.API.R=R; +Obj.API.N=N; + +% store IR data +Obj.Data.IR = NaN(M,R,N); % data.IR must be [M R N] +for aa=1:M + HpIR = [BTDEI.data(aa).HpIR; zeros((N-length(BTDEI.data(aa).HpIR)),2)]; + Obj.Data.IR(aa,1,:)= HpIR(:,1)'; + Obj.Data.IR(aa,2,:)= HpIR(:,2)'; +end + + +% update dimensions +Obj = SOFAupdateDimensions(Obj); +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..1d8c818b355c939b002b11fbefa3cf58f980ade8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m @@ -0,0 +1,61 @@ +function Obj=SOFAconvertCIPIC2SOFA(CIPIC) +% Obj=SOFAconvertCIPIC2SOFA(CIPIC) converts the HRTFs described in the structure CIPIC +% (see CIPIC HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +ida=round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1)); +lat=lat1(ida); + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,size(CIPIC.hrir_l,3)); % data.IR must be [M R N] +Obj.Data.SamplingRate = 44100; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=CIPIC.hrir_l(aa,ee,:); + Obj.Data.IR(ii,2,:)=CIPIC.hrir_r(aa,ee,:); + [azi,ele]=hor2sph(-lat(ii),pol(ii)); + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = CIPIC.name; +Obj.GLOBAL_History = 'Converted from the CIPIC file format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; +% SimpleFreeFieldHRIR 0.3 and 0.4 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..5fc3fb679bbe611737d93a84337a61d578702a0a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m @@ -0,0 +1,83 @@ +function Obj=SOFAconvertFHK2SOFA(miroObj) +% OBJ=SOFAconvertFHK2SOFA(miroObj) converts the HRTFs described in miroObj +% to SOFA. miroObj is the miro object saved at the Fach-Hochschule Köln +% provided by Benjamin Bernschütz. +% Reference to the source format: http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +% Reference to the source coordinate system: [1] http://code.google.com/p/sofia-toolbox/wiki/COORDINATES + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% if isoctave, +if exist('OCTAVE_VERSION','builtin') ~= 0 + error('Octave is not able to convert FHK to SOFA, use Matlab instead.'); +end + +%% Check if miro.m class file is available, if not download file from server +% miro class might also be included in other toolboxes, eg. AKtools +if exist('miro','class') ~= 8 + % download miro.m + disp('Downloading miro.m from TH Köln server...') + url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m'; + basepath=which('SOFAstart'); + basepath=basepath(1:end-12); % Kill the function name from the path. + target=[basepath filesep 'helpers' filesep 'miro.m']; + websave (target,url); +end + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = miroObj.irChOne; % irChOne is [N M] +Obj.Data.IR(:,:,2) = miroObj.irChTwo; +Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +% Obj.GLOBAL_APIName +% Obj.GLOBAL_ApplicationName +% Obj.GLOBAL_ApplicationVersion +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = miroObj.context; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Fachhochschule Köln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_References = 'Bernschütz, B. (2013). "A Spherical Far Field HRIR/HRTF Compilation of the Neumann KU 100", proceedings of the AIA/DAGA, Meran, Italy'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Origin = 'http://www.audiogroup.web.fh-koeln.de/ku100hrir.html'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='FHK'; +Obj.GLOBAL_Title = 'HRTF'; + +%% Fill the mandatory variables +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + % From [1]: All angles are in RAD. + % AZ denotes the azimutal angle in a range of (0-2pi(. Whereas AZ=0 is defined to be the front direction and AZ=pi to be the rear direction. + % EL denotes the elevation angle in a range of (0-pi). EL=0 points upwards, EL=pi/2 points to the horizontal plane and EL=pi points downwards. + % r is the radius in meters (if needed/specified). +Obj.SourcePosition = [... + rad2deg(miroObj.azimuth') ... % miroObj.azimuth is AZ + 90-rad2deg(miroObj.elevation') ... % miroObj.elevation is EL + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % miro.sourceDistance is r + +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +%Obj.GLOBAL_EmitterDescription =''; +Obj.GLOBAL_RoomDescription = miroObj.location; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..3005699ddefb22c1e876563129116d625051af5a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m @@ -0,0 +1,45 @@ +function Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) +% Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) converts the HRTFs described in LISTEN +% (see LISTEN HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data + % content_m is [M N], data.IR must be [M R N] +Obj.Data.IR = zeros(size(LISTEN.l_eq_hrir_S.content_m,1),2,size(LISTEN.l_eq_hrir_S.content_m,2)); +Obj.Data.IR(:,2,:)=LISTEN.r_eq_hrir_S.content_m; +Obj.Data.IR(:,1,:)=LISTEN.l_eq_hrir_S.content_m; +Obj.Data.SamplingRate = 48000; % Note: LISTEN.l_eq_hrir_S.sampling_hz contains 44100 which is wrong! + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = subjectID; +Obj.GLOBAL_History='Converted from the LISTEN format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.95 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v zeros(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v 1.95*ones(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8e3f2e47b763dd6ec3cb6e2161081e780b32b8d3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m @@ -0,0 +1,86 @@ +function Obj=SOFAconvertMIT2SOFA(root,pinna) +% OBJ=SOFAconvertMIT2SOFA(root,pinna) loads the MIT HRTFs saved in a +% directory ROOT for the PINNA and converts to a SOFA object. +% PINNA must be 'normal' or 'large'. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Create correct parts of the file name +% 'L' use full data from left pinna (normal pinna) +% 'R' use full data from right pinna (large red pinna) +% 'H' use compact data -> not supported now +switch pinna + case 'normal' + postfix='L'; idx=[1 2]; + prefix='full'; + case 'large' + postfix='R'; idx=[2 1]; + prefix='full'; + otherwise + error('Pinna not supported'); +end + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90]; +elecnt=[ 56 60 72 72 72 72 72 60 56 45 36 24 12 1]; + +%% Determine data size +M=sum(elecnt); +Obj.SourcePosition=zeros(M,3); +if isfile([root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav']) + Obj.Data.IR=zeros(M,2,length(audioread([root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav']))); +else + warning(['File not existing: ' root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav' ' --> Please download it to: ' root filesep prefix filesep 'elev0' filesep]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + flip_azi = mod(360-azi,360); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(flip_azi)) 'a.wav']; + Obj.Data.IR(ii,idx(1),:) = audioread(fn)'; % data.IR must be [M R N] + dirfn=dir(fn); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(azi)) 'a.wav']; + Obj.Data.IR(ii,idx(2),:) = audioread(fn)'; + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1.4]; + ii=ii+1; + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = ['KEMAR, ' pinna ' pinna']; +Obj.GLOBAL_History='Converted from the MIT format'; +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 +% Obj.ListenerPosition = [1.4 0 0]; +% Obj.ListenerView = [-1 0 0]; +% Obj.ListenerUp = [0 0 1]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..22ffd2e9a97fe84139aa0aa2376744af0099ed88 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m @@ -0,0 +1,75 @@ +function Obj=SOFAconvertSCUT2SOFA(root,r) +% OBJ=SOFAconvertSCUT2SOFA(root,pinna) loads the SCUT HRTFs saved in a +% directory ROOT for the radius R and converts to a SOFA object. +% R must be in meters. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-30 -15 0 15 30 45 60 75 90]; +elecnt=[ 72 72 72 72 72 72 36 24 1]; + +%% Create empty matrix +M=sum(elecnt)*length(r); +Obj.SourcePosition=zeros(M,3); +Obj.Data.IR=zeros(M,2,512); + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for jj=1:length(r) + for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + fn=fullfile(root, ['r' num2str(r(jj)*100)], ['ele' num2str(ele)], ['H' num2str(azi) 'c.pcm']); + dirfn=dir(fn); + if isempty(dirfn) % check if HRTF sources are available + error(['HRTF files not available in: ' fullfile(root, ['r' num2str(r(jj)*100)], ['ele' num2str(ele)])]); + end + fid = fopen(fn, 'r'); + H = fread(fid,'float'); + fclose(fid); + Obj.Data.IR(ii,1,:) = single(H(1:2:1024)); % separate the left-ear HRIR + Obj.Data.IR(ii,2,:) = single(H(2:2:1024)); % separate the right-ear HRIR + Obj.SourcePosition(ii,:) = [mod(360-azi,360) ele r(jj)]; + ii=ii+1; + end + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the SCUT format'; + +Obj.GLOBAL_Author = 'Bosun Xie'; +Obj.GLOBAL_AuthorContact = 'phbsxie@scut.edu.cn'; +Obj.GLOBAL_License = 'CC 3.0 BY-SA-NC'; +Obj.GLOBAL_Organization = 'South China University of Technology, Guangzhou, China'; + +Obj.GLOBAL_References = 'Bosun Xie, 2013, "Head-Related Transfer Function and Virtual Auditory Display", J Ross Publishing Inc., Plantation, FL, USA'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_DatabaseName='SCUT'; + +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + + +%% Fill the mandatory variables +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..0391042cc29b57888ad059573cce7d16ffc4c544 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m @@ -0,0 +1,70 @@ +function [hM,meta,stimPar]=SOFAconvertSOFA2ARI(Obj) +% [hM, meta, stimPar]=SOFAconvertSOFA2ARI(Obj) converts a SOFA object HRTFs +% to HRTFs described in hM, meta, and stimPar (see ARI HRTF format). +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR'), + error('ARI Format supports only SimpleFreeFieldHRIR SOFA conventions'); +end + +%% Fill data matrix +hM=shiftdim(Obj.Data.IR,2); % data.IR is [M R N], hM must be [N M R] + +%% Fill stimPar +stimPar.SamplingRate = Obj.Data.SamplingRate; +stimPar.TimeBase = 1e6/stimPar.SamplingRate; +stimPar.SubjectID = Obj.GLOBAL_ListenerShortName; + +%% Fill meta + % Fill in geodesic coordinate system where azi=(0;360) and ele=(-90;90); +meta.pos(:,1)=bsxfun(@times,Obj.SourcePosition(:,1),ones(Obj.API.M,1)); +meta.pos(:,2)=bsxfun(@times,Obj.SourcePosition(:,2),ones(Obj.API.M,1)); + % Fill in the Channel +if isfield(Obj,'MeasurementSourceAudioChannel'), + meta.pos(:,3) = bsxfun(@times,Obj.MeasurementSourceAudioChannel,ones(Obj.API.M,1)); +else + meta.pos(:,3) = NaN(Obj.API.M,1); +end +if isfield(Obj,'MeasurementAudioLatency'), + meta.lat=bsxfun(@times,Obj.MeasurementAudioLatency,ones(Obj.API.M,1)); +end + % create horizontal-polar coordinates +[meta.pos(:,6), meta.pos(:,7)]=sph2hor(meta.pos(:,1),meta.pos(:,2)); + % create continuous-elevation coordinates where azi=(-90;90) and ele=(0;360); +meta.pos(:,4)=meta.pos(:,1); +meta.pos(:,5)=meta.pos(:,2); +idx=find(meta.pos(:,1)>90 & meta.pos(:,1)<=270); +meta.pos(idx,4)=meta.pos(idx,4)-180; +meta.pos(idx,5)=180-meta.pos(idx,5); +idx=find(meta.pos(:,1)>270 & meta.pos(:,1)<=360); +meta.pos(idx,4)=meta.pos(idx,4)-360; + +%% Fill with unknown but probably mandatory data +% stimPar.Channel = 0; +% stimPar.Electrode = 0; +% stimPar.PulseNr = 0; +% stimPar.Period = 0; +% stimPar.Offset = 0; +stimPar.Resolution = 24; % assume a 24-bit ADC/DAC resolution +% stimPar.FadeIn = 0; +% stimPar.FadeOut = 0; +% stimPar.Length = 0; +% stimPar.FittFileName = ''; +% stimPar.StimFileName = ''; +stimPar.GenMode = 1; +% stimPar.WorkDir = ''; +stimPar.ID = 'hrtf'; +stimPar.Version = '2.0.0'; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..dc01c37d17278e811c683381bcd8151b1ed24129 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m @@ -0,0 +1,79 @@ +function [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) +% [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) converts objects +% from SYMARE database to Struct in SOFA format. +% +% SYMAREpath of type string specifies the path where the SYMARE directory +% is found +% HRIRname of type string specifies which HRIR out of the +% <SYMAREpath>/HRIRs/Acoustic directory should be converted +% +% Returns Obj in SOFA format which can further be converted into .sofa +% file using SOFAsave + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: license added, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Get an empty conventions structure + +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); +Obj.GLOBAL_Title = 'HRIR'; +Obj.GLOBAL_RoomType = 'free field'; + +%% Fill global attributes +if isempty(strfind(HRIRname,'.mat')) + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-1:end)); +else + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-5:end-4)); +end + +Obj.GLOBAL_AuthorContact ='https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_Comment = ''; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History', ... + 'Converted from the SYMARE database'); +Obj.GLOBAL_License = strcat('Creative Commons Attribution-Non', ... + 'Commercial-ShareAlike 4.0 International Public License'); +Obj.GLOBAL_Organization = 'University of Sydney'; +Obj.GLOBAL_Author = 'Craig Jin, Anthony Tew, et al.'; +Obj.GLOBAL_Origin = 'https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_DateCreated = char(datetime('now','Format','yyyy-MM-dd HH:mm:ss.SSS')); +Obj.GLOBAL_DatabaseName='SYMARE'; + +%% Get SYMARE data and convert to SOFA structure +%m: number of measurements; +%R: number of receivers; +%n: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%HRIR Dimensions : mRn; + +% Get source positions +load(fullfile(SYMAREpath,'HRIRs','Parameters','azim')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','elev')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','r')); +if ~(length(r) == length(azim)) + r(1:size(azim)) = r; + r = r'; +end +Obj.SourcePosition = [azim*180/pi,elev*180/pi,r]; + +% Get sampling frequency +load(fullfile(SYMAREpath,'HRIRs','Parameters','fs')); +Obj.Data.SamplingRate = fs; + +% Get IRs +load(fullfile(SYMAREpath,'HRIRs','Acoustic',HRIRname)); % gets you hR, hL +HRIR(:,:,1) = hL'; % nm -> mnR +HRIR(:,:,2) = hR'; % nm -> mnR +Obj.Data.IR = permute(HRIR,[1 3 2]); % mnR -> mRn + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..027181b2e657e1f122585d21cf2ac37fb2ce04ca --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m @@ -0,0 +1,155 @@ +function Obj = SOFAconvertTHK2SOFA(miroObj) +% OBJ=SOFAconvertTHK2SOFA(miroObj) converts the HRIRs, BRIRs, and DRIRs +% (VariSphear array measurements) described in miroObj to SOFA. +% miroObj is the miro object saved at the Technische Hochschule Koeln, provided by Benjamin Bernschuetz. +% Reference to the source format: http://www.audiogroup.web.th-koeln.de/FILES/miro_documentation.pdf +% Reference to the source coordinate system: [1] http://www.audiogroup.web.th-koeln.de/SOFiA_wiki/COORDINATES.html +% SOFAconvertTHK2SOFA written by Tim Lübeck, TH Köln, 2018 +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% +%if isoctave, +if exist('OCTAVE_VERSION','builtin') ~= 0 + error(['Octave is not able to convert THK to SOFA, use Matlab instead.']); +end + +%% Check if miro.m class file is available, if not download file from server +% miro class might also be included in other toolboxes, eg. AKtools +if exist('miro','class') ~= 8 + % download miro.m + disp('Downloading miro.m from TH Köln server...') + url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m'; + basepath=which('SOFAstart'); + basepath=basepath(1:end-12); % Kill the function name from the path. + target=[basepath filesep 'helpers' filesep 'miro.m']; + websave (target,url); +end + +%% Get an empty conventions structure depending on miro format +if ( strcmp (miroObj.type,'HRIR') ) + Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_Title = 'HRIR'; + Obj.GLOBAL_RoomType = 'free field'; + typeFlag = 0; +elseif ( strcmp (miroObj.type,'BRIR') ) + Obj = SOFAgetConventions('MultiSpeakerBRIR'); + Obj.GLOBAL_Title = 'BRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 1; +else %( strcmp (miroObj.type,'MICARRAY') ) + Obj = SOFAgetConventions('SingleRoomDRIR'); + Obj.GLOBAL_Title = 'DRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 2; +end + +%% Fill global attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = [miroObj.context,' / Sampling Grid: ',miroObj.quadGrid]; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Technische Hochschule Koeln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_Origin = 'http://audiogroup.web.th-koeln.de'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='THK'; +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +Obj.GLOBAL_EmitterDescription = miroObj.source; +Obj.GLOBAL_RoomDescription = [miroObj.location,' / avgAirTemp: ',num2str(miroObj.avgAirTemp),' / avgRelHumidity: ',num2str(miroObj.avgRelHumidity)]; + +%% Set miroObj to degree mode +miroObj.shutUp = 1; +miroObj = setDEG(miroObj); + +%% Get miroObject data and convert to SOFA structure +%M: number of measurements; +%R: number of receivers; +%N: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%FIR : [M R N]; + +if (typeFlag == 0 || typeFlag == 1) %BRIR or HRIR + irChOne = zeros(miroObj.returnTaps,miroObj.nIr); + irChTwo = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + IR = getIR( miroObj, channel ); + irChOne(:, channel) = IR(:,1); %[N M] + irChTwo(:, channel) = IR(:,2); %[N M] + end + if (typeFlag == 0) %HRIR + Obj.Data.IR = irChOne; % irChOne is [N M] + Obj.Data.IR(:,:,2) = irChTwo; + Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] + else % BRIR + Obj.Data.IR = zeros(size(irChOne,2), 2, 1, size( irChTwo,1)); %[N 2 1 M] + Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irChOne,-2),3); + Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irChTwo,-2),3); + end +else % DRIR + irData = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + irData(:,channel) = miroObj.getIR(channel); + end + Obj.Data.IR = zeros(1, miroObj.nIr ,miroObj.returnTaps); %[M R N] + for R = 1 : miroObj.nIr + Obj.Data.IR(1,R,:) = irData(:,R); + end + Obj.Data.Delay = zeros(1,miroObj.nIr); +end +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill the mandatory source emitter variables +Obj.ListenerPosition = [0 0 0]; % for BRIR and HRIR listener in center +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; % for HRIR and BRIR ears as receiver + +if (typeFlag == 0)%HRIR + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.SourcePosition = [... + miroObj.azimuth' ... % azimuth angle in a range of (0-360°(. Whereas AZ=0° is defined to be the front direction and AZ=180° to be the rear direction. + 90-miroObj.elevation' ... % elevation angle in range of (0-180°). EL=0 points upwards, EL=90° points to the horizontal plane and EL=180° points downwards. + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % radius in meters +elseif (typeFlag == 1) %BRIR + Obj.SourcePosition = [0 0 0]; % default edit manually! + Obj.EmitterPosition = [miroObj.sourceDistance 0 0]; % default position is center, otherwise define manually + Obj.EmitterPosition_Type = 'cartesian'; + Obj.EmitterUp = [0 0 1]; + Obj.EmitterView = [-1 0 0]; + Obj.ListenerView = [miroObj.azimuth', ... % see HRIR definitions + 90-miroObj.elevation', ... + zeros(size(miroObj.azimuth'))]; %miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ListenerUp = [0 0 1]; +else %DRIR + Obj.SourcePosition = [1,0,0]; % default edit manually! + Obj.EmitterPosition = [0,0,0]; + Obj.ListenerPosition = [0 0 0]; + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ReceiverPosition = [... + miroObj.azimuth' ... + 90-miroObj.elevation' ... + miroObj.radius*ones(size(miroObj.azimuth'))]; + Obj.ReceiverPosition_Type = 'spherical'; + Obj.ReceiverPosition_Units = 'degree, degree, metre'; +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..6f1150b3fafdaf770745aae0f1544c8ef2540233 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m @@ -0,0 +1,58 @@ +function Obj=SOFAconvertTUBerlin2SOFA(irs) +% OBJ=SOFAconvertTUBerlin2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(shiftdim(irs.left,-1),2); % irs.left is [N M], data.IR must be [M R N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-1),2); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HRTF from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['H. Wierstorf, M. Geier, A. Raake, S. Spors. ', ... + 'A Free Database of Head-Related Impulse Response Measurements in ', ... + 'the Horizontal Plane with Multiple Distances. ', ... + 'In 130th Convention of the Audio Engineering Society, May 2011.']; +Obj.GLOBAL_Origin = 'https://dev.qu.tu-berlin.de/projects/measurements/repository/show/2010-11-kemar-anechoic/mat'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = irs.ears; +Obj.GLOBAL_SourceDescription = irs.source; + +%% Fill the mandatory variables +% SimpleFreeFieldHRIR 0.6 +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.SourcePosition = [nav2sph(rad2deg(irs.apparent_azimuth)') ... + rad2deg(irs.apparent_elevation)' ... + distance.*ones(M,1)]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..4c24ed7d1de931345f17044705ff6d144bcf74ff --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m @@ -0,0 +1,74 @@ +function Obj=SOFAconvertTUBerlinBRIR2SOFA(irs) +% OBJ=SOFAconvertTUBerlinBRIR2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object, using the MultiSpeakerBRIR +% Convention. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('MultiSpeakerBRIR'); + +%% Fill data with data +Obj.Data.IR = zeros(size(irs.left,2),2,1,size(irs.left,1)); +Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irs.left,-2),3); % irs.left is [N M], data.IR must be [M R E N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-2),3); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'BRIR from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['']; +Obj.GLOBAL_Origin = 'TU Berlin'; +Obj.GLOBAL_Organization = 'Quality and Usability Lab, Technische Universitaet Berlin'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'BRIR TU Berlin'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = 'Large ears (KB0065 + KB0066) with G.R.A.S. 40AO pressure microphones'; +Obj.GLOBAL_SourceDescription = 'Genelec 8030A'; +Obj.GLOBAL_RoomType = 'reverberant'; +Obj.GLOBAL_RoomDescription = ''; + + +%% Fill the mandatory variables +% MultiSpeakerBRIR +% === Source === +Obj.SourcePosition = [0 0 0]; % center of loudspeaker array +Obj.EmitterPosition = irs.source_position'; +Obj.EmitterView = irs.head_position'; +Obj.EmitterUp = [0 0 1]; +% === Listener === +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.ListenerPosition = irs.head_position'; +[x,y,z] = sph2cart(fixnan(irs.head_azimuth'), ... + repmat(fixnan(irs.head_elevation'),size(irs.head_azimuth')), ... + repmat(distance,size(irs.head_azimuth'))); +Obj.ListenerView = [x,y,z]; +Obj.ListenerUp = [0 0 1]; +% Receiver position for a dummy head (imported from SimpleFreeFieldHRIR) +Obj.ReceiverPosition = [0,0.09,0; 0,-0.09,0]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end + +function x = fixnan(x) + if isnan(x), x=0; end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m new file mode 100644 index 0000000000000000000000000000000000000000..ac6cb698bbbb9bebf1c320e6fe4633fc230aef7d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m @@ -0,0 +1,172 @@ +function [dtf,ctf]=SOFAhrtf2dtf(hrtf,varargin) +%SOFAHRTF2DTF splits HRTFs into directional transfer functions (DTFs) and +%common transfer functions (CTFs) +% Usage: [dtf,ctf]=SOFAhrtf2dtf(hrtf) +% [dtf,ctf]=SOFAhrtf2dtf(hrtf,f1,f2) +% +% Input parameters: +% hrtf: SOFA object with SimpleFreeFieldHRIR convention +% +% Output arguments: +% dtf: SOFA object with the directional transfer functions +% ctf: SOFA object with the common transfer functions +% +% `SOFAhrtf2dtf(...)` calculates DTFs using the method from either +% Majdak et al. (2010; 'log' flag) or Middlebrooks (1999; 'rms' flag). +% The magnitude spectrum of the CTF is calculated by +% averaging the (log-)magnitude spectra across all HRTFs for each ear. +% The phase spectrum of the CTF is the minimum phase +% corresponding to the magnitude spectrum of the CTF. +% DTFs result from filtering the HRTF with the inverse complex CTF. +% +% `SOFAhrtf2dtf` accepts the following key-value pairs: +% +% 'f1',f1 start frequency of the filtering (in Hz; default: 50 Hz) +% 'f2',f2 end frequency of the filtering (in Hz; default: 18 kHz) +% 'atten',a broadband attenuation in order to avoid clipping (in dB; +% default: 20 dB) +% 'weights' w area weights for averaging. Vector of size [M 1] +% (M=number of HRIRs), or flase (default: false) +% +% `SOFAhrtf2dtf` accepts the following flags: +% +% 'log' evaluate CTF magnitude spectrum by average of log-magnitude +% spectra, equivalent to geometric mean of linear filters +% (c.f., Majdak et al., 2010; Baumgartner et al., 2014). +% This is the default. +% 'rms' evaluate CTF magnitude spectrum by RMS of linear +% magnitude spectra, equivalent to diffuse-field +% compensation (c.f., Middlebrooks, 1999; Moller et al., +% 1995). +% +% References: +% Baumgartner, R., Majdak, P., & Laback, B. (2014). Modeling sound-source +% localization in sagittal planes for human listeners. J. Acoust. Soc. Am. +% 136(2), 791-802. +% Majdak, P., Goupell, M. J., & Laback, B. (2010). 3-D localization of +% virtual sound sources: Effects of visual environment, pointing method, +% and training. Attention, Perception, & Psychophysics, 72(2), 454-469. +% Middlebrooks, J. C. (1999). Individual differences in external-ear +% transfer functions reduced by scaling in frequency. J. Acoust. Soc. Am., +% 106(3), 1480-1492. +% Moller, H., Hammershoi, D., Jensen, C. B., S?rensen, M. F. (1995). +% Design criteria for headphones. J. Audio Eng. Soc., 43(4), 218-232. + +% #Author: Robert Baumgartner (16.01.2014) +% #Author: Fabian Brinkmann: added rms, and weighted averaging (08.09.2016) +% #Author: Piotr Majdak: Octave ifft compatibility (23.02.2018) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Check Input +definput.keyvals.f1 = 50; % Hz +definput.keyvals.f2 = 18000; % Hz +definput.keyvals.atten = 20; % dB +definput.keyvals.weights = false; +definput.flags.avg = {'log','rms'}; + +[flags,kv]=SOFAarghelper({'f1','f2','atten', 'weights'},definput,varargin); + +%% Settings +kv.fs = hrtf.Data.SamplingRate; +hrtfmtx = shiftdim(hrtf.Data.IR,2); % dim 1: time, dim 2: source position, dim 3: receiver/ear +N = size(hrtfmtx,1); +Nfft = N; %2^nextpow2(N); + +%% Frequency bounds +df = kv.fs/Nfft; +f = 0:df:kv.fs-df; +idx = f >= kv.f1 & f <= kv.f2; +idx(Nfft/2+2:end) = fliplr(idx(2:Nfft/2)); + +%% CTF calculation + +% get magnitude response +hrtff=fft(hrtfmtx,Nfft); +if flags.do_rms + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg=sqrt(sum( abs(hrtff).^2 .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2 )); + else + ctffavg=sqrt(mean(abs(hrtff).^2,2)); + end +else % flags.do_log + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg= sum(log(abs(hrtff)+eps) .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2); + else + ctffavg=mean(log(abs(hrtff)+eps),2); + end +end + +% Force minimum phase +ctfflog=mean(log(abs(hrtff)+eps),2); +ctfcep = ifft(ctfflog,Nfft); +ctfcep(Nfft/2+2:Nfft,:,:) = 0; % flip acausal part to causal part or simply multiply +ctfcep(2:Nfft/2,:,:) = 2*ctfcep(2:Nfft/2,:,:); % causal part by 2 (due to symmetry) +ctfflog = fft(ctfcep,Nfft); +ctfp = exp(ctfflog); + +% get complex spectrum +if flags.do_rms + ctff = ctffavg .*exp(1j*angle(ctfp)); +else + ctff = exp(ctffavg) .*exp(1j*angle(ctfp)); +end + +% get IR +ctfmtx = real(ifft(ctff, Nfft)); + +%% DTF calculation +dtff = hrtff; +dtff(idx,:,:) = hrtff(idx,:,:)./repmat(ctff(idx,:,:),[1 size(hrtff,2) 1]); +dtfmtx = ifft(dtff,Nfft); + +%% Attenuate to avoid clipping +ctfmtx = ctfmtx / 10^(kv.atten/20); +dtfmtx = dtfmtx / 10^(kv.atten/20); + +%% Output Objects +dtf = hrtf; +if size(dtfmtx,3)==1 % handle objects with R=1 + dtfmtx(1,1,2)=0; + dtfmtx = shiftdim(dtfmtx,1); + dtf.Data.IR = dtfmtx(:,1,:); +else + dtf.Data.IR = shiftdim(dtfmtx,1); +end +if ~isfield(dtf, 'GLOBAL_Comment'), dtf.GLOBAL_Comment=''; end +dtf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Directional transfer functions (DTFs) were generated by removing from the HRTFs the direction-independent log-amplitude spectrum for each ear.']; + +ctf = hrtf; +if size(ctfmtx,2)==1 % handle objects with R=1 + ctf.Data.IR = shiftdim(shiftdata([ctfmtx ctfmtx],3),2); + ctf.Data.IR = ctf.Data.IR(1,:,:); +else + ctf.Data.IR = shiftdim(ctfmtx,1); +end +ctf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Common transfer functions (CTFs) were extracted from the HRTFs in terms of averaging the log-amplitude spectrum for each ear. The phase of a CTF is determined as minimum phase.']; +ctf.SourcePosition = [0 0 0]; + % remove non-standard variables +fc=fieldnames(ctf); +fo=fieldnames(SOFAgetConventions(ctf.GLOBAL_SOFAConventions)); +f=setdiff(fc,fo); % get non-standard fields +f(strncmpi(f,'GLOBAL_',7)) = []; % variables only +ctf=rmfield(ctf,f); % remove +ctf.API.Dimensions=rmfield(ctf.API.Dimensions,f); +ctf = SOFAupdateDimensions(ctf); + + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end; +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..780bb8e50218d149806f89e16ed5643b552b9dc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m @@ -0,0 +1,39 @@ +function [azi,ele]=hor2sph(lat,pol) +%HOR2SPH transform horizontal-polar to spherical coordinates. +% [azi,ele]=hor2sph(lat,pol) +% +% Input: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also SPH2HOR, SPH2NAV, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Robert Baumgartner +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - function hor2sph +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[x,nz,y] = sph2cart(-deg2rad(pol),deg2rad(lat),ones(size(lat))); + +[azi,ele,r] = cart2sph(x,y,-nz); + +azi = rad2deg(azi); +ele = rad2deg(ele); + +% adjust azimuth range +[azi,ele] = nav2sph(azi,ele); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..47e34d2bfc09f535f55b98b6f8ad586bacc9378f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m @@ -0,0 +1,28 @@ +function [azi,ele]=nav2sph(azi,ele) +%NAV2SPH Coordinate Transform. +% [azi,ele] = nav2sph(azi,ele) vonverts navigational coordinates to +% spherical coordinates. +% +% Input: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also HOR2SPH, SPH2HOR, SPH2NAV, SPH2HOR, SPH2SH + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function nav2sph +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +idx=find(azi<0); % azi between -180 and 0 deg +azi(idx) = azi(idx)+360; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m new file mode 100644 index 0000000000000000000000000000000000000000..d9ee4571c2360363c9c511f62b7c840a43990773 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m @@ -0,0 +1,64 @@ +function [S, N_SH] = sph2SH(dirs, L) +%[S, N_SH] = sph2SH(dirs, L); +% sph2SH calculates real-valued spherical harmonics for directions dirs = [azi ele] (in degrees) up to order L. +% +% Input: +% dirs ... dirs = [azi ele] +% L ... order L +% +% Output: +% S ... real-valued spherical harmonics +% N_SH ... number of SH coefficients +% +% See also HOR2SPH, SPH2HOR, SPH2NAV, SPH2HOR, NAV2SPH + +% #Author: Piotr Majdak: adapted from getSH.m from https://github.com/polarch/Spherical-Harmonic-Transform (24.07.2020) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - function sph2SH +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + + N_dirs = size(dirs, 1); % number of discrete positions + N_SH = (L+1)^2; % number of SH coefficients + dirs=deg2rad(dirs); % convert to radiant + dirs(:,2) = pi/2 - dirs(:,2); % convert to zenith angle + + S = zeros(N_SH, N_dirs);% matrix with the coefficients + + % n = 0, direction-independent component + Llm = legendre(0, cos(dirs(:,2)')); + Nlm = sqrt(1./(4*pi)) * ones(1,N_dirs); + CosSin = zeros(1,N_dirs); + CosSin(1,:) = ones(1,size(dirs,1)); + S(1, :) = Nlm .* Llm .* CosSin; + + % n > 0, direction-dependent components + idx = 1; + for l=1:L + + m = (0:l)'; + + Llm = legendre(l, cos(dirs(:,2)')); + condon = (-1).^[m(end:-1:2);m] * ones(1,N_dirs); + Llm = condon .* [Llm(end:-1:2, :); Llm]; + + mag = sqrt( (2*l+1)*factorial(l-m) ./ (4*pi*factorial(l+m)) ); + % create the ACN ordering: [m<0; m=0; m>0] + Nlm = [mag(end:-1:2) * ones(1,N_dirs); mag * ones(1,N_dirs)]; + + CosSin = zeros(2*l+1,N_dirs); + CosSin(l+1,:) = ones(1,size(dirs,1)); % m=0 + CosSin(m(2:end)+l+1,:) = sqrt(2)*cos(m(2:end)*dirs(:,1)'); % m>0 + CosSin(-m(end:-1:2)+l+1,:) = sqrt(2)*sin(m(end:-1:2)*dirs(:,1)'); % m<0 + + S(idx+1:idx+(2*l+1), :) = Nlm .* Llm .* CosSin; + idx = idx + 2*l+1; + end + + S = S.'; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m new file mode 100644 index 0000000000000000000000000000000000000000..420dca0c384161169a60aeecb94de7cb1676ca37 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m @@ -0,0 +1,42 @@ +function [lat,pol]=sph2hor(azi,ele) +%SPH2HOR transform spherical to horizontal-polar coordinates. +% [lat,pol]=sph2hor(azi,ele) +% +% Input: +% azi ... azimuth (in degrees) +% ele ... elevation (in degrees) +% +% Output: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% See also HOR2SPH, SPH2NAV, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Robert Baumgartner +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function sph2hor +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +[x,y,z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(size(azi))); + +% remove noise below eps +x(abs(x)<eps)=0; +y(abs(y)<eps)=0; +z(abs(z)<eps)=0; + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[pol,nlat,r] = cart2sph(x,z,-y); +pol = rad2deg(pol); +lat = rad2deg(-nlat); + +% adjust polar angle range +pol = mod(pol+90,360)-90; +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m new file mode 100644 index 0000000000000000000000000000000000000000..b7fe3a0c403676c717a68340517f6be50609b20e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m @@ -0,0 +1,31 @@ +function [azi,ele] = sph2nav(azi,ele) +%SPH2NAV Coordinate Transform +% [azi,ele] = sph2nav(azi,ele) converts spherical coordinates to +% navigational coordinates. +% +% Input: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% See also HOR2SPH, SPH2HOR, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function sph2nav +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +azi=mod(azi,360); % wrap to 0 to 360 +idx=find(azi>180 & azi<=360); % azi between 180 and 360 +azi(idx) = -(360-azi(idx)); + +end % end of function \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..fa7d95ab7951c36b00f6a13d273a8c41a131770e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m @@ -0,0 +1,46 @@ +% SOFA Toolbox - demo script +% Load HRTF in ARI format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert (use default if not defined) +if ~exist('subjectID','var'); subjectID='NH4'; end +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); + +if isfile(ARIfn) + disp(['Loading: ' ARIfn]); + ARI=load(ARIfn); +else + warning(['File not existing: ' ARIfn ' --> Please download it from http://www.oeaw.ac.at/isf/hrtf and save it to: ' fullfile(fileparts(SOFAdbPath), 'ARI', subjectID)]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + + +%% convert +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); +Obj.GLOBAL_DatabaseName = 'ARI'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['ARI_' subjectID '_' ARIfile '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..fd2d65d51aa277fe06fa29aa48b05178b58d688a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m @@ -0,0 +1,65 @@ +% SOFA Toolbox demo script +% load HRTF in BT-DEI format and save in SOFA format. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Headphone index of the files to convert +hp= 'H010'; +% Subject index of the files to convert +subject= 'S115'; +% Measurement index of the files to convert +setm= 'Set02'; %Set01 Set02 ... +% File name of the BTDEI file +BTDEIfold='COMPENSATED'; %RAW %COMPENSATED %EQUALIZED +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load BTDEI file \ load database structure data +f=filesep; +BTDEI_hp_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,'headphones_info.mat'); +BTDEI_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,subject,setm,BTDEIfold,'MAT',[hp '_' subject '_btdei.mat']); +disp(['Loading BT-DEI data']); + +try + datasheet = load(BTDEI_hp_add); + BTDEI.hp = datasheet.hp_specs; + + switch subject + case 'S115' + BTDEI.sbjType = 'dummy head with large pinna'; + case 'S116' + BTDEI.sbjType = 'dummy head without pinna'; + case 'S117' + BTDEI.sbjType = 'dummy head without pinna'; + otherwise + BTDEI.sbjType = 'human'; + end + + container = load(BTDEI_add); + BTDEI.specs = container.specs; + BTDEI.data = container.data; +catch e + error(['Load BTDEI file - Error message: ' e.message ' Try downloading the BT-DEI database from: http://padva.dei.unipd.it/?page_id=345 to the corresponding directory.']); +end + +BTDEI.type = BTDEIfold; +BTDEI.typeset = setm; + +%% convert +Obj = SOFAconvertBTDEI2SOFA(BTDEI); +Obj.GLOBAL_Comment = SOFAappendText(Obj,'GLOBAL_Comment',BTDEIfold); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['BTDEI-hp_' hp '_subj_' subject '-' setm '-' BTDEIfold '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..eb571b48a7bc3180ed0d3c54273e218c855120b2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m @@ -0,0 +1,36 @@ +% load HRTF in CIPIC format and save in SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID=3; +% File name of the CIPIC file +CIPICfile='hrir_final'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load CIPIC file +CIPICfn=fullfile(fileparts(SOFAdbPath), 'CIPIC', ['subject_' sprintf('%03d',subjectID)], [CIPICfile '.mat']); +disp(['Loading: ' CIPICfn]); +CIPIC=load(CIPICfn); + +%% convert +Obj=SOFAconvertCIPIC2SOFA(CIPIC); +Obj.GLOBAL_DatabaseName = 'CIPIC'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test', ['CIPIC_' 'subject_' sprintf('%03d',subjectID) '_' CIPICfile '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..19ef9ce31e245f834545a87d4c8a766ab67ae41f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m @@ -0,0 +1,62 @@ +% load HRTF in FHK format and save in SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Octave has no support for the miro class of the FHK data +% if isoctave +if exist('OCTAVE_VERSION','builtin') ~= 0 + warning(['demo_FHK2SOFA does not work in Octave.' newline 'Octave is not able to convert FHK to SOFA, use Matlab instead.']); + return; +end + +%% Check if miro.m class file is available, if not download file from server +% miro class might also be included in other toolboxes, eg. AKtools +if exist('miro','class') ~= 8 + % download miro.m + disp('Downloading miro.m from TH K�ln server...') + url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m'; + basepath=which('SOFAstart'); + basepath=basepath(1:end-12); % Kill the function name from the path. + target=[basepath filesep 'helpers' filesep 'miro.m']; + websave (target,url); +end + +% load HRTF in FHK format and save as SOFA format + +%% Define parameters +% Get a file name of the FHK directory +d=dir(fullfile(fileparts(SOFAdbPath),'FHK','HRIR_*.mat')); +if isempty(d) + error(['No HRTF files available: ' fullfile(fileparts(SOFAdbPath),'FHK','HRIR_*.mat')]); +end +fn=d(1).name; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load FHK file +FHKfn=fullfile(fileparts(SOFAdbPath), 'FHK', fn); +disp(['Loading: ' FHKfn]); +FHK=load(FHKfn); +FHKvar=fieldnames(FHK); +FHKname=FHKvar{1}; +FHKdata=FHK.(FHKname); + +%% convert +Obj=SOFAconvertFHK2SOFA(FHKdata); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['FHK_' FHKname '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m new file mode 100644 index 0000000000000000000000000000000000000000..ca59a8a3a635465cc59078c3ccca141eb58b7033 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m @@ -0,0 +1,74 @@ +% Demonstrates the usage of the FreeFieldDirectivityTF conventions. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: '(demo_)plot_trumpet_directivity' added to this script (19.02.2022) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% close all; + +clear fn; +fn{1}='ITA_Dodecahedron.sofa'; +fn{2}='Trumpet_modern_et_ff_all_tensorData.sofa'; +% fn{3}='Trumpet_modern_et_ff_a4_rawData.sofa'; % (21 MB!!! uncomment if you don't mind, or have downloaded it already) + + +for ii=1:length(fn) + Obj=SOFAload(['db://database/tu-berlin (directivity)/' fn{ii}]); + + % % update dimensions to see if it works + % D=SOFAupdateDimensions(D, 'verbose',1); + + % plot the geometry because why not + SOFAplotGeometry(Obj); + + % move every figure a little to the right from previous one + H=gcf; + % if ~isoctave; if ii>1; movegui(H,[(H.Position(1)+(ii-1)*300) H.Position(2)]); end; end + if exist('OCTAVE_VERSION','builtin') == 0; if ii>1; movegui(H,[(H.Position(1)+(ii-1)*300) H.Position(2)]); end; end + + % set title + title(strrep(char(fn(ii)),'_',' ')); + disp([' Figure ' num2str(ii) ' of ' num2str(length(fn))+1 ' plotted: ' strrep(char(fn(ii)),'_',' ')]); +end + + +%% plot_trumpet_directivity +% original code from Fabian Brinkmann (12.2021), adapted by Michael Mihocic (2021-2022) +% requires AKp.m, check dependencies, otherwise skip this part +if exist('AKp.m', 'file') + + % load Data + H = SOFAload('db://database/tu-berlin%20(directivity)/Trumpet_modern_a4_fortissimo.sofa'); + + p = H.Data.Real(:,:,1) + 1j * H.Data.Imag(:,:,1); + p_log = 20*log10(p/max(abs(p))); + + % plot + AKf(20) + AKp(p_log, 'x2', 'g', H.ReceiverPosition(:, 1:2), 'dr', [-10 0], ... + 'hp_view', [30 45], 'cm', 'RdBu_flip', 'cb', 0, ... + 'sph_proc', 'interpSpline1'); + title '' + + AKtightenFigure; + disp(' Figure 3 of 3 plotted: Trumpet_modern_a4_fortissimo.sofa'); +else + warning(' Figure 3 of 3 skipped: Trumpet_modern_a4_fortissimo.sofa'); + disp(' To plot this figure you need to:'); + disp(' - download AKtools.zip (release) from: https://www.ak.tu-berlin.de/menue/publications/open_research_tools/aktools/'); + disp(' - extract the zip file'); + disp(' - run AKtoolsStart.m'); + disp(' - add the path of AKtoolsStart.m to Matlab (including subdirectories!)'); +end + +%% +disp(' '); +disp('### demo_FreeFieldDirectivityTF: done ###'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..8787ae7d5726992cded804cea54ee36f735dbd3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m @@ -0,0 +1,64 @@ +% Demonstrates the usage of the FreeFieldHRIR conventions. + +% #Author: Michael Mihocic (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='FreeFieldHRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..45dda7fba262b69dae814e5f6ef76e19ecb19418 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m @@ -0,0 +1,268 @@ +% Demonstrates the usage of spherical harmonics (SH) for HRTF interpolation. +% demo_FreeFieldHRTF loads an HRTF set, transforms to TF, then to SH, then +% samples the horizontal and median plane in steps of 0.5 degrees. Finally, +% the files are saved in SOFAdbPath as demo_FreeFieldHRTF_{TF, SH, TFrec}.sofa. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: save figures as optional parameter added, figures are saved with respective titles as names (10.11.2021) +% #Author: Michael Mihocic: minor bugs fixed (28.12.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +savefigures=0; % save all created figures as fig and png (0: no, 1: yes) +if savefigures==1 + close all; % clean-up first + warning('off', 'MATLAB:MKDIR:DirectoryExists'); % suppress warning if folder exists + mkdir ([mfilename('fullpath') ' figures']); % output folder for figures + folder=[mfilename('fullpath') ' figures' filesep]; +end + +%% Let's start, load a SimpleFreeFieldHRIR SOFA object +IR=SOFAload('db://database/thk/HRIR_L2354.sofa'); +fs=IR.Data.SamplingRate; +IR.GLOBAL_APIVersion=SOFAgetVersion; +%% Figures +figure; +SOFAplotHRTF(IR,'magmedian'); +tit='SimpleFreeFieldHRIR (FIR, mag), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +% print([folder tit '.png'], '-dpng'); +end + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_1_IR.sofa'),IR); + +%% Convert to TF +TF=SOFAgetConventions('SimpleFreeFieldHRTF'); +TF.ListenerPosition=IR.ListenerPosition; +TF.ListenerPosition_Type=IR.ListenerPosition_Type; +TF.ListenerPosition_Units=IR.ListenerPosition_Units; +TF.ListenerView=IR.ListenerView; +TF.ListenerView_Type=IR.ListenerView_Type; +TF.ListenerView_Units=IR.ListenerView_Units; +TF.ListenerUp=IR.ListenerUp; +TF.SourcePosition=IR.SourcePosition; +TF.SourcePosition_Type=IR.SourcePosition_Type; +TF.SourcePosition_Units=IR.SourcePosition_Units; +TF.EmitterPosition=IR.EmitterPosition; +TF.EmitterPosition_Type=IR.EmitterPosition_Type; +TF.EmitterPosition_Units=IR.EmitterPosition_Units; +TF.ReceiverPosition=IR.ReceiverPosition; +TF.ReceiverPosition_Type=IR.ReceiverPosition_Type; +TF.ReceiverPosition_Units=IR.ReceiverPosition_Units; + +TF.Data.Real=zeros(IR.API.M,IR.API.R,IR.API.N+1); +TF.Data.Imag=zeros(IR.API.M,IR.API.R,IR.API.N+1); +for ii=1:IR.API.M + for jj=1:IR.API.R + sp=fft(squeeze(IR.Data.IR(ii,jj,:)),2*IR.API.N); % Delay not considered! + TF.Data.Real(ii,jj,:)=real(sp(1:IR.API.N+1,:)); + TF.Data.Imag(ii,jj,:)=imag(sp(1:IR.API.N+1,:)); + end +end +TF.N=(0:fs/2/IR.API.N:fs/2)'; + +TF=SOFAupdateDimensions(TF); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_2_TF.sofa'),TF); + +%% Plot median plane and horizontal planes for reference +figure; +SOFAplotHRTF(TF,'magmedian'); +tit='SimpleFreeFieldHRTF (TF, mag), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(TF,'etchorizontal'); +tit='SimpleFreeFieldHRTF (TF, etc), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% Convert to an emitter-based representation, TFE +TFE=TF; +TFE.GLOBAL_SOFAConventions = 'GeneralTF-E'; +TFE.GLOBAL_DataType = 'TF-E'; +TFE.API.E=TF.API.M; +TFE.API.M=1; +TFE.Data=rmfield(TFE.Data,{'Real','Imag'}); +TFE.Data.Real(1,:,:,:)=shiftdim(TF.Data.Real,1); % MRN --> 1RNM --> MRNE with M=1 +TFE.API.Dimensions.Data.Real='MRNE'; +TFE.Data.Imag(1,:,:,:)=shiftdim(TF.Data.Imag,1); +TFE.API.Dimensions.Data.Imag='MRNE'; +TFE.EmitterPosition=TF.SourcePosition; +TFE.EmitterPosition_Type=TF.SourcePosition_Type; +TFE.EmitterPosition_Units=TF.SourcePosition_Units; +TFE.API.Dimensions.EmitterPosition='ECI'; +TFE.SourcePosition=[0 0 0]; +TFE.API.Dimensions.SourcePosition='IC'; + +TFE=SOFAupdateDimensions(TFE); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_3_TFE.sofa'),TFE); + +%% Convert to SH +SH=TFE; +SH.GLOBAL_SOFAConventions = 'FreeFieldHRTF'; + +Lmax=floor(sqrt(size(SH.EmitterPosition,1))-1); % Max SH order +L=40; % actual SH order +[S, SH.API.E]=sph2SH(SH.EmitterPosition(:,1:2), L); + +Sinv=pinv(S); +SH.Data.Real=zeros(1, SH.API.R, SH.API.N, SH.API.E); +SH.Data.Imag=zeros(1, SH.API.R, SH.API.N, SH.API.E); +for ii=1:TFE.API.R + for jj=1:TFE.API.N + SH.Data.Real(1,ii,jj,:)=Sinv*squeeze(TFE.Data.Real(1,ii,jj,:)); + SH.Data.Imag(1,ii,jj,:)=Sinv*squeeze(TFE.Data.Imag(1,ii,jj,:)); + end +end + +SH.EmitterPosition=mean(SH.EmitterPosition); +SH.EmitterPosition_Type='Spherical Harmonics'; + +SH = SOFAupdateDimensions(SH); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_4_SH.sofa'),SH); + +%% plot median and horizonal planes - spatially continuous +figure; +SOFAplotHRTF(SH,'magmedian'); %title(''); +tit='FreeFieldHRTF (TFE, mag) in Spherical Harmonics'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(SH,'etchorizontal'); %title (''); +tit='FreeFieldHRTF (TFE, etc) in Spherical Harmonics'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot spatially continuous geometry +SOFAplotGeometry(SH); +tit='FreeFieldHRTF (TFE, geometry) in Spherical Harmonics'; % title +% if ~isoctave +if exist('OCTAVE_VERSION','builtin') == 0 + fig=gcf; + fig.Position(3:4)=[600,400]; % increase size (supported in Matlab only) +end +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot spatial spectra +figure; +for y=1:4 + subplot(2,2,y); hold on; + fax=0:fs/(2*SH.API.N):(fs-(fs/(2*SH.API.N)))/2; + r=1; plot(fax,20*log10(squeeze(abs(SH.Data.Real(1,r,:,y)+1i*SH.Data.Imag(1,r,:,y))))); + r=2; plot(fax,20*log10(squeeze(abs(SH.Data.Real(1,r,:,y)+1i*SH.Data.Imag(1,r,:,y)))),'r'); + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + tit=['SH spectra, coefficient index (ACN)= ' num2str(y)]; + title(tit); +end +subplot(2,2,1);legend('First receiver','Second receiver'); +if savefigures==1 + tit='SH spectra'; + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot all coefficients for a given frequency +figure; hold on; +f=10000; k=round(f/fs*2*SH.API.N); +plot(squeeze(20*log10(abs(SH.Data.Real(1,1,k,:)+1i*SH.Data.Imag(1,1,k,:)))),'ob'); +hold on; +plot(squeeze(20*log10(abs(SH.Data.Real(1,2,k,:)+1i*SH.Data.Imag(1,2,k,:)))),'xr'); +% title(); +xlabel('Coefficients (ACN index)'); +ylabel('Magnitude (dB)'); +legend('First receiver','Second receiver'); + +tit=['SH representation, frequency = ' num2str(f) ' Hz']; % title +title(tit); +if savefigures==1 + tit='SH representations'; % title + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + + +%% interpolate for the horizontal and median planes to FreeFieldHRTF (TFE) +TFEint=SH; +elemin=-90; +ele=[elemin:1:90 89:-1:elemin zeros(1,length(1:355))]'; +azi=[zeros(length(elemin:1:90),1); 180*ones(length(89:-1:elemin),1); (1:355)']; +radius=SH.EmitterPosition(:,3)*ones(size(ele)); +TFEint.EmitterPosition=[azi ele radius]; +TFEint.EmitterPosition_Type='spherical'; +TFEint.EmitterPosition_Units=SH.EmitterPosition_Units; +Sint = sph2SH(TFEint.EmitterPosition(:,1:2), L); +TFEint.API.E=size(Sint,1); +TFEint.Data.Real=zeros(1,2,TFEint.API.N,TFEint.API.E); +TFEint.Data.Imag=zeros(1,2,TFEint.API.N,TFEint.API.E); +for ii=1:TFEint.API.R + for jj=1:TFEint.API.N + TFEint.Data.Real(1,ii,jj,:)=Sint*squeeze(SH.Data.Real(1,ii,jj,:)); + TFEint.Data.Imag(1,ii,jj,:)=Sint*squeeze(SH.Data.Imag(1,ii,jj,:)); + end +end + +TFEint=SOFAupdateDimensions(TFEint); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_5_TFEint.sofa'),TFEint); + +%% interpolate for the horizontal and median planes to SimpleFreeFieldHRTF (TF) +TFint=TF; +ele=[-90:0.5:90 89:-.5:-90 zeros(1,length(1:0.5:355))]'; +azi=[zeros(length(-90:.5:90),1); 180*ones(length(89:-.5:-90),1); (1:0.5:355)']; +radius=1.2*ones(size(ele)); +TFint.SourcePosition=[azi ele radius]; +Sint = sph2SH(TFint.SourcePosition(:,1:2), sqrt(SH.API.E)-1); +TFint.API.M=size(Sint,1); +TFint.Data.Real=zeros(TFint.API.M,2,TFint.API.N); +TFint.Data.Imag=zeros(TFint.API.M,2,TFint.API.N); +for ii=1:TFint.API.R + for jj=1:TFint.API.N + TFint.Data.Real(:,ii,jj)=Sint*squeeze(SH.Data.Real(1,ii,jj,:)); + TFint.Data.Imag(:,ii,jj)=Sint*squeeze(SH.Data.Imag(1,ii,jj,:)); + end +end + +TFint=SOFAupdateDimensions(TFint); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_6_TFint.sofa'),TFint); + +%% compare +figure; +SOFAplotHRTF(TFint,'magmedian'); %title(''); +tit='SimpleFreeFieldHRTF (TF, mag), interpolated'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(TFint,'etchorizontal'); % title(''); +tit='SimpleFreeFieldHRTF (TF, etc), interpolated'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m new file mode 100644 index 0000000000000000000000000000000000000000..a2b7c1a87c9419df29865307eaac767c61d9cbfd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m @@ -0,0 +1,40 @@ +% Demonstrates the usage of the General conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='General'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.API.E=1; +Obj.Data.IR=rand(4800,1); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m new file mode 100644 index 0000000000000000000000000000000000000000..842ef389d8bc513bc908725e64c079fe3fd52acf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m @@ -0,0 +1,65 @@ +% Demonstrates the usage of the GeneralFIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='GeneralFIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] +Obj.Data.Delay=[0 0]; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m new file mode 100644 index 0000000000000000000000000000000000000000..9f9f9fc2086f540f73c0dcf7fa72dc4ac079e037 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m @@ -0,0 +1,65 @@ +% Demonstrates the usage of the GeneralFIR-E conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='GeneralFIR-E'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] +Obj.Data.Delay=[0 0]; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m new file mode 100644 index 0000000000000000000000000000000000000000..bbe277b63ff5d6db5bd5b2081393f6ceabd5229b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m @@ -0,0 +1,43 @@ +% Demonstrates the usage of the GeneralTF conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +% clear; +conventions='GeneralTF'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.ReceiverPosition=[0,0.09,0]; +Obj.SourcePosition=[1,0,0;0,1,0;-1,0,0;0,-1,0]; +% Fill some random data +Obj.Data.Real=[-0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024]; +Obj.Data.Imag=[0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m new file mode 100644 index 0000000000000000000000000000000000000000..e9cdde7ca57add1f4cfa392b0df2653df3212c61 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m @@ -0,0 +1,45 @@ +% Demonstrates the usage of the GeneralTF-E conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +% clear; +conventions='GeneralTF-E'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.ReceiverPosition=[0,0.09,0]; +Obj.SourcePosition=[1,0,0;0,1,0;-1,0,0;0,-1,0]; +% Fill some random data +% Obj.Data.Real=[-0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024]; +% Obj.Data.Imag=[0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005]; +Obj.Data.Real=rand(4,4800); +Obj.Data.Imag=rand(4,4800); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..6190b9aa8b6b2d09a39f3dfd167dede77ac58be4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m @@ -0,0 +1,42 @@ +% load HRTF in LISTEN format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +if ~exist('subjectID','var'); subjectID='1002'; end +% File name of the LISTEN file +LISTENfile=['IRC_' subjectID '_C_HRIR']; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load LISTEN file +LISTENfn=fullfile(fileparts(SOFAdbPath),'LISTEN',['IRC_' subjectID],'COMPENSATED','MAT','HRIR',[LISTENfile '.mat']); +if isfile(LISTENfn) + disp(['Loading: ' LISTENfn]); + LISTEN=load(LISTENfn); +else + warning(['File not existing: ' LISTENfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath),'LISTEN',['IRC_' subjectID],'COMPENSATED','MAT','HRIR')]); + error(['Sorry.... ' mfilename ' cannot complete! The following file is missing: ' LISTENfile '.mat']); +end + +%% convert +Obj=SOFAconvertLISTEN2SOFA(LISTEN,subjectID); +Obj.GLOBAL_DatabaseName = 'LISTEN'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['LISTEN_' subjectID '_' LISTENfile '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..17bc908327b810b38c4bd17600fea728741b3a49 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m @@ -0,0 +1,37 @@ +% load HRTF in MIT format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Two ears are available: normal and large. Select one or define before running this script. +if ~exist('pinna','var') + pinna='normal'; +end + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +MITfn=fullfile(fileparts(SOFAdbPath),'MIT KEMAR'); +disp(['Loading: ' MITfn ', pinna:' pinna]); + +%% load and convert +Obj=SOFAconvertMIT2SOFA(MITfn,pinna); +Obj.GLOBAL_DatabaseName = 'MIT'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['MIT_KEMAR_' pinna '_pinna.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..4a3ba286799a2c208ad7291b3f8db6b97e720dbb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the MultiSpeakerBRIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='MultiSpeakerBRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.Data.IR=rand(4800,2); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m new file mode 100644 index 0000000000000000000000000000000000000000..ac2b4ce34a757e3b5cad84d8552559b5a48fa1d9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m @@ -0,0 +1,35 @@ +% SOFA Toolbox - test script +% Test audio playback after convolving sound file + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% put your information here: +hrtf = SOFAload('path/to_your/HRTF.sofa'); % Load your impulse response into a struct +soundInput = audioread('path/to_your/fancy_audio_file.wav'); % Load your sound file + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(hrtf.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..e9e7c2139b7e2bb83c4ff7605039acd8a54d488b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m @@ -0,0 +1,40 @@ +% load HRTF in MIT format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Two ears are available: normal and large. Select one. +pinna='normal'; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +SCUTdata = 'nearfield'; +SCUTroot=fullfile(fileparts(SOFAdbPath),'SCUT',SCUTdata); +disp(['Loading: ' SCUTroot]); + +%% Define radii for converting +radius=[0.2 0.25 0.3:0.1:1]; +% radius=0.2; + +%% load and convert +Obj=SOFAconvertSCUT2SOFA(SCUTroot,radius); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +str=sprintf('%g,',radius); +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['SCUT_KEMAR_radius_' str(1:end-1) '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..24c31341b7cfb0a71f39d3632c4983b1ae78eea1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m @@ -0,0 +1,42 @@ +% load HRTF in SOFA format and save as ARI format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); +disp(['Loading: ' ARIfn]); +ARI=load(ARIfn); + +%% convert from ARI to SOFA +disp('Converting to SOFA...'); +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); + +%% convert back from SOFA to ARI +disp('Converting back to ARI (hM, meta, stimPar)...'); +[hM, meta, stimPar]=SOFAconvertSOFA2ARI(Obj); + +%% Calculate the differences +disp(['RMS difference between the new hM and the original ARI.hM: ' num2str(sum(sum(sqrt(mean((hM-ARI.hM).^2)))))]); +if sum(sum(sqrt(mean((hM-ARI.hM).^2))))>1, error('hM and ARI.hM not identic'); end +disp(['RMS difference between the new meta.pos and the original ARI.meta.pos: ' num2str(sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2))))]); +if sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2)))>1, error('meta.pos and ARI.meta.pos not identic'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m new file mode 100644 index 0000000000000000000000000000000000000000..def227d2fdfaf56cb82e61da8b90515424cbf977 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m @@ -0,0 +1,69 @@ +% load HRTF and plots CTF and average DTF +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define parameters +% Subject index of the file to convert +subject=3; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'database', 'cipic', ['subject_' sprintf('%03d',subject) '.sofa']); +X=SOFAload(SOFAfn); + +if exist('OCTAVE_VERSION','builtin') + % We're in Octave + pkg load signal; % for 'shiftdata' compatibility +end + +[D,C]=SOFAhrtf2dtf(X); + +% close all; +f = figure; +set(f, 'Position', [50, 400, 1100, 500]); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,1,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(C.Data.IR(1,1,1:length(C.Data.IR)/2)))))); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,2,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +[D,CC]=SOFAhrtf2dtf(D); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('left'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best') + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,1:length(C.Data.IR)/2))))),'r'); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,2,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('right'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m new file mode 100644 index 0000000000000000000000000000000000000000..339e4f6f304ac45411108b227fd99fa9ba382e60 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m @@ -0,0 +1,43 @@ +% load HRTF and plots ITD + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. +% + +%% Define parameters +% Subject index of the file to convert +subject=3; + +%% load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'database', 'cipic', ['subject_' sprintf('%03d',subject) '.sofa']); +Obj=SOFAload(SOFAfn, 'nochecks'); + +%% Calculate Interaural time delay +[itd_time, ~, ~, Obj_time] = SOFAcalculateITD(Obj, 'time', 'thr', 20); +[itd_samples, ~, ~, Obj_samples] = SOFAcalculateITD(Obj, 'samples', 'thr', 20); + +%% Plot results +h = figure(); +subplot(211) +plot((Obj_time.Data.Delay(:,1) - Obj_time.Data.Delay(:,2))*1e6) +xlabel('Position') +ylabel('Time (\mus)') +axis tight + +subplot(212) +plot((Obj_samples.Data.Delay(:,1) - Obj_samples.Data.Delay(:,2))) +xlabel('Position') +ylabel(['Samples (Fs:' num2str(Obj.Data.SamplingRate), 'Hz)']) +axis tight + +%% Polar plot (not working in Octave) +SOFAplotHRTF(Obj, 'itdhorizontal'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m new file mode 100644 index 0000000000000000000000000000000000000000..806bf50201abc12048719d1f7687e500c6fb4fbb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m @@ -0,0 +1,87 @@ +% load HRTF and extends low frequency content +% + +% #Author: Davi Carvalho +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. +% + +clear; % clc; close all; + +SOFAfile=fullfile(SOFAdbPath,'database','cipic','subject_003.sofa'); +Obj=SOFAload(SOFAfile); + + +%% Low frequency extension +fmin = 15; +fmax = 500; +Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax); + + +%% general properties +fs = Obj.Data.SamplingRate; +% HRIRs +IR = shiftdim(Obj.Data.IR, 2); +IR_lfe = shiftdim(Obj_lfe.Data.IR, 2); +% Number of samples +N = size(IR, 1); +N_lfe = size(IR_lfe, 1); +% Time vector +tx = 0:1/fs:(N-1)/fs; +tx_ext = 0:1/fs:(N_lfe-1)/fs; +% Frequency vector +freq = (0:N/2-1)*fs/N; +freq_lfe = (0:N_lfe/2-1)*fs/N_lfe; + + +%% PLOTS +ch = 1; % ear +pos = 100; % position index + +%%% Plot time +figure() +plot(tx, IR(:,pos,ch)); hold on +plot(tx_ext(1:N), IR_lfe(1:N, pos, ch), '--','linewidth', 1.3); hold off +legend('original', 'LFE', 'location', 'best') +xlabel('Time (ms)') +axis tight + +%%% Plot freq +figure() +ori = mag2db(abs(fft(IR(:,pos,ch), N_lfe))); +lfe = mag2db(abs(fft(IR_lfe(:,pos,ch)))); +semilogx(freq_lfe, ori(1:N_lfe/2)); hold on +semilogx(freq_lfe, lfe(1:N_lfe/2), '--','linewidth', 1.3); hold off +legend('original', 'LFE', 'location', 'best') +xlabel('Frequency (Hz)') +ylabel('Amplitude (dB)') +axis tight + +% %% Phase +% t = 0:1/1e3:10; +% fo = 0; +% f1 = 500; +% y = chirp(t,fo,t(end),f1,'linear',0,'complex'); +% figure +% semilogx(angle(fft(y))) +% title('phase') + +%% +figure +SOFAplotHRTF(Obj,'maghorizontal'); +figure +SOFAplotHRTF(Obj_lfe,'maghorizontal'); + + + + + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..c3c196a6318ab79290729766c95bf02bc2c8e708 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m @@ -0,0 +1,55 @@ +% This demo shows how to use SOFAexpand and SOFAcompact +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Expanding the objects +x=whos('Obj'); +disp('Expanding the objects'); +tic; +clear Expanded +for ii=1:length(radius) + Expanded(ii)=SOFAexpand(Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Expanded'); +disp([' Expanded object array is now larger by ' num2str(round((y.bytes-x.bytes)/1024)) ' kb']); + +%% Compress the object +disp('Compressing the objects'); +tic; +clear Compacted +for ii=1:length(radius) + Compacted(ii)=SOFAcompact(Expanded(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Compacted'); +disp([' Compacted object array is now as small as the original one. Difference: ' num2str(round((x.bytes-y.bytes)/1024)) ' kb']); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..79de42b828a2285512a4e65470b62b367526d969 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m @@ -0,0 +1,78 @@ +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Path definitions +SOFAfile=fullfile(SOFAdbPath, 'database', 'tu-berlin', 'qu_kemar_anechoic_all.sofa'); + +%% Loading the full object +disp(['Loading full object: ' SOFAfile]); +tic; +ObjFull=SOFAload(SOFAfile); +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% Loading metadata +disp('Loading all metadata and partial data only'); +tic; +Meta=SOFAload(SOFAfile,'nodata'); + +%% Get index of measurements with the same directions +azi=0; ele=0; +idx=find(Meta.SourcePosition(:,1)==azi & Meta.SourcePosition(:,2)==ele); + +%% Load the parts of the full objects +disp('Loading partial data only'); +clear Obj +for ii=1:length(idx); + Obj(ii)=SOFAload(SOFAfile,[idx(ii) 1]); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('Obj'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Load parts of multiple dimensions of the full object +%e.g. only left ear for source positions 0�-90� at distance 1m +tic +idxSTART=find(Meta.SourcePosition(:,1)==0 & Meta.SourcePosition(:,3)==1); +idxEND=find(Meta.SourcePosition(:,1)==90 & Meta.SourcePosition(:,3)==1); +idxCOUNT=idxEND-idxSTART+1; +disp('Loading partial data in multiple dimensions') +ObjPartMultDim=SOFAload(SOFAfile,[idxSTART idxCOUNT],'M',[1 1],'R'); +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('ObjPartMultDim'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Extract and plot the fully loaded data +IRsFull=squeeze(ObjFull.Data.IR(idx,1,:)); +legFull=num2str(ObjFull.SourcePosition(idx,3)); +subplot(1,2,1); +plot(IRsFull'); +legend(legFull); +title(['Demo of SOFAload:' 10 ... + 'Fully loaded data']); +xlabel(['Index (Sample Taps), fully loaded']); +ylabel('Amplitude'); + +%% Extract and plot the partially loaded data +IRs=zeros(length(idx), Obj(1).API.N); +for ii=1:length(idx) + IRs(ii,:)=squeeze(Obj(ii).Data.IR(:,1,:)); + leg{ii}=num2str(Obj(ii).SourcePosition(:,3)); +end +subplot(1,2,2); +plot(IRs'); +legend(leg); +title(['IRs for the left ear with radius as parameter' 10 ... + 'Partially loaded data']); +xlabel(['Index (Sample Taps), partially loaded']); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..0e3e28d79a25de3493595ba324024ecc14aca15d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m @@ -0,0 +1,64 @@ +% This demo shows how to use SOFAmerge +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA +% +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects to be merged +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Merging the objects +disp('Merging to a single SOFA object'); +tic; +ObjFull=Obj(1); +for ii=2:length(radius) + ObjFull=SOFAmerge(ObjFull,Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% save the object as a single SOFA file +warning('off','SOFA:save'); +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[TUBfile 'radius_' sprintf('%g_',radius) 'm.sofa']); +disp(['Saving: ' SOFAfn]); +tic; +Obj=SOFAsave(SOFAfn, ObjFull, compression); +x=whos('ObjFull'); +disp(['Saved ' num2str(round(x.bytes/1024)) ' kb in ' num2str(toc) ' s.']); + +%% Plot IRs for a single direction but different radius +azi=0; ele=0; +idx=find(Obj.SourcePosition(:,1)==azi & Obj.SourcePosition(:,2)==ele); +plot(squeeze(ObjFull.Data.IR(idx,1,:))'); +legend(num2str(ObjFull.SourcePosition(idx,3))) +title(['Demo of SOFAmerge:' 10 ... + 'IRs for the left ear with radius as parameter retrieved from a merged object']); +xlabel(' index (sample taps)'); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m new file mode 100644 index 0000000000000000000000000000000000000000..4650b0d87a738fa76b44c3d36f447cbc43cc7305 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m @@ -0,0 +1,64 @@ +% demo_SOFAplotGeometry - script demonstrating the usage of +% SOFAplotGeometry +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file in SimpleFreeFieldHRIR + +SOFAfile=fullfile(SOFAdbPath,'database','widespread','ICO1m_00139.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +% plot all measurements +SOFAplotGeometry(Obj); + +% % only show every 45th measurement +index = 1:45:Obj.API.M; +SOFAplotGeometry(Obj,index); + +% %% load a SingleRoomDRIR SOFA file +disp(['Loading: ' 'db://' fullfile('database','thk','DRIR_LBS_VSA_1202RS_SBL.sofa')]); +Obj=SOFAload(['db://' ... + fullfile('database','thk','DRIR_LBS_VSA_1202RS_SBL.sofa')]); + +% plot SOFA Object with 1202 Receivers +SOFAplotGeometry(Obj); + +% % remove all but one Receiver +Obj.ReceiverPosition = [0 0.09 0]; +Obj.ReceiverPosition_Type = 'cartesian'; +Obj.Data.IR = Obj.Data.IR(:,1,:); +Obj.Data.Delay = Obj.Data.Delay(:,1,:); +Obj = SOFAupdateDimensions(Obj); + +SOFAplotGeometry(Obj); + +% %% load a GeneralFIR SOFA file +SOFAfile=fullfile(SOFAdbPath,'database', 'tu-berlin','FABIAN_CTF_modeled.sofa'); +Obj = SOFAload(SOFAfile); + +SOFAplotGeometry(Obj); + +% %% load example with room geometry +disp(['Loading: ' SOFAfile]); +SOFAfile = fullfile(SOFAdbPath,'sofatoolbox_test', 'Oldenburg_OfficeII.sofa'); +Obj = SOFAload(SOFAfile); + +SOFAplotGeometry(Obj); + +% %% if exists try plotting SOFA file containing spherical harmonic emitter +% if exist(fullfile(SOFAdbPath,'demo_SHforHRTFs_SH.sofa')) +% Obj = SOFAload(fullfile(SOFAdbPath,'demo_SHforHRTFs_SH.sofa')); +% SOFAplotGeometry(Obj); +% else +% error('Run demoSHforHRTFS.m first.') +% end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..c1813c46e700aaaa333861bfae06f8a3205648f5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m @@ -0,0 +1,35 @@ +% demo_SOFAplotHRTF - script demonstrating the usage of SOFAplotHRTF + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file in SimpleFreeFieldHRIR +SOFAfile=fullfile(SOFAdbPath,'database','ari','dtf_nh2.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +% plot ETC horizontal plane +figure; +SOFAplotHRTF(Obj,'ETCHorizontal',1); +% plot magnitude spectrum in the median plane, channel 2 +figure; +SOFAplotHRTF(Obj,'MagMedian',2); + +%% load a GeneralTF SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari (sim)','hrtf_nh5_ref.sofa'); +Obj=SOFAload(SOFAfile); +% plot magnitude spectrum in the median plane, channel 1 +figure; +SOFAplotHRTF(Obj,'MagMedian',1); +figure; +SOFAplotHRTF(Obj,'MagMedian',1,'convert',0); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..2d42da3d56b25a2fdb38ee4efde0e655959a645a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m @@ -0,0 +1,73 @@ +%% +% This demo creates an artificial HRTF set. +% It shows how to use SOFAgetConventions and SOFAsave +% The HRTF set contains single pulses placed at sample index of 100 +% which results in a broadband delay of 100 samples. +% Each IR is 256 samples long (i.e., N=256) + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Set parameters +% Latency of the created IRs +latency=100; % in samples, must be 1<latency<256 +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Get an empy conventions structure +disp('Creating SOFA file with SimpleFreeFieldHRIR conventions...'); +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +%% Create the impulse response +N=256; +IR=[zeros(latency,1); 1; zeros(N-latency-1,1)]; + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History = 'created with a script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','Pulse.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..e7a0f0cb9717ab4cdd58676e1d385e67d15b33af --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m @@ -0,0 +1,60 @@ +% SOFA Toolbox - demo script + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define the filename of the SOFA HRTFs +database='ari'; HRTFfilename='hrtf_nh4.sofa'; +% database='cipic'; HRTFfilename='subject_003.sofa'; +% database='listen'; HRTFfilename='irc_1002.sofa'; +% database='mit'; HRTFfilename='mit_kemar_normal_pinna.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_0.5m.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_all.sofa'; + +%% Define the trajectory +azi=[-45 90 0]; % azimuth angles in degrees. If negative values are found, navigational system (-180;+180) will be used. +ele=[0 0 -30 90]; %elevation angles in degrees + +%% Load the HRTFs +fullfn=fullfile(SOFAdbPath, 'database', database, HRTFfilename); +disp(['Loading ' fullfn]); +Obj=SOFAload(fullfn); + +%% Create an input signal +in=randn(5*Obj.Data.SamplingRate,1); % Five seconds of noise +fade=round(0.02*Obj.Data.SamplingRate); % fade in and out for 20 ms +win=hanning(fade*2); +in(1:fade)=in(1:fade).*win(1:fade); +in(end-fade+1:end)=in(end-fade+1:end).*win(fade+1:end); +%% Spatialize +[out,azi,ele,idx]=SOFAspat(in,Obj,azi,ele); +disp('Binaural signal rendered'); + +%% Plot the trajectories +time = (1:length(azi))/Obj.Data.SamplingRate; + +figure +subplot(2,1,1); +plot(time,azi); % plot azimuthal trajectory +ylabel('Azimuth (deg)'); +title('SOFAspat: Trajectory'); + +subplot(2,1,2); +plot(time,ele); % plot elevational trajectory +ylabel('Elevation (deg)'); +xlabel('Time (s)'); + +%% Play the sound - use headphones! +if ~exist('dontplay','var'); + p=audioplayer(out, Obj.Data.SamplingRate); + play(p); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m new file mode 100644 index 0000000000000000000000000000000000000000..47616c7d35e2debcacac42fb257728371e36d11c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m @@ -0,0 +1,84 @@ +% Script for testing the string array feature of SOFA + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: updated with variable ReceiverDescriptions instead of Ears (03.08.2022) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Test Strings as application-specific variable +% Load some arbritrary HRTFs +hrtf = SOFAload(fullfile(SOFAdbPath, 'database','ari','dtf_nh2.sofa')); +% Add a string array +str={}; +for ii=1:hrtf.API.M + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +% SOFAaddVariable(Obj,Name,Dim,Value) +hrtf2 = SOFAaddVariable(hrtf,'Test','MS',str); + +% Add a new string with dimensions [RS] +strn={'left ear'; 'right ear'}; +hrtf2 = SOFAaddVariable(hrtf2, 'ReceiverDescriptions', 'RS', strn); + +% Save as SOFA +SOFAsave('stringtest_applicationvar.sofa',hrtf2); +% Reload the file +hrtf = SOFAload('stringtest_applicationvar.sofa'); +% compare the strings +if prod(strcmp(hrtf.Test,hrtf2.Test)) + disp('SimpleFreeFieldHRIR: String Load-Reload: OK'); + delete('stringtest_applicationvar.sofa'); +else + error('String comparison showed differences'); +end +clear + +%% Test with conventions GeneralString (non-standardized convention, just for testing) +% Create an empty object +Obj = SOFAgetConventions('GeneralString'); +% Create numeric data with M=15, R=2, N=10 +Obj.Data.Double=rand(15,2,10); +% Create string arrays +str2={}; str={}; +for ii=1:15 + id = num2str(round(rand(1,1)*1000000)); + str{ii,1}=['X' id]; + str2{ii,1}=['Left' id]; + str2{ii,2}=['Right' id]; +end +Obj.String2 = str2; % String1=[MRS] +Obj.Data.String1 = str; % Data.String1=[MS] +Obj.Data.String2 = str2; % Data.String2=[MRS] + +% Add a new string with dimensions [RS] +strn={'left ear'; 'right ear'}; +Obj = SOFAaddVariable(Obj, 'ReceiverDescriptions', 'RS', strn); + +% Update dimensions +Obj = SOFAupdateDimensions(Obj); +% Save as SOFA +SOFAsave('stringtest_generalstring.sofa',Obj); +% Reload the file +Obj2 = SOFAload('stringtest_generalstring.sofa'); +% Compare the strings +if ~prod(strcmp(Obj2.Data.String2,Obj.Data.String2)) + error('Data.String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.String2,Obj.String2)) + error('String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.Data.String1,Obj.Data.String1)) + error('Data.String1: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.ReceiverDescriptions,Obj.ReceiverDescriptions)) + error('ReceiverDescriptions: Comparison showed differences'); +end +disp('GeneralString: String1, String2, Data, ReceiverDescriptions: Load-Reload: OK'); +clear +delete('stringtest_generalstring.sofa'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m new file mode 100644 index 0000000000000000000000000000000000000000..5b0cff7487553798c5be7d70562fb365200952f4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m @@ -0,0 +1,64 @@ +% SOFA Toolbox - script demonstrating the usage of variables in the API + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari','hrtf_nh5.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +%% read an API internal variable +M=Obj.API.M; % read M, the number of measurements +disp(['The number of measurements, M, is ' num2str(M)]); + +%% add a user-defined variable and check it + % create a random variable with the size M +myvar=rand(M,1); + % add to Obj +Obj=SOFAaddVariable(Obj,'MyVariable','M',myvar); + % check if it's there and identical to the created one +if ~all((Obj.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the size is M +if ~all(size(Obj.MyVariable)==[M 1]), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% add a private variable + % create a random variable with the size 1000 x 10 +privatevar=rand(1000,10); + % add to Obj as private +Obj=SOFAaddVariable(Obj,'MyVariable','Private',privatevar); + % check if it's there and identical to the created one +if ~all((Obj.PRIVATE.MyVariable-privatevar)<=eps('single')), error('Error!'); end + % check if the size is 1000 x 10 +if ~all(size(Obj.PRIVATE.MyVariable)==[1000 10]), error('Error!'); end + +%% Save the object + % create a random file name +fn=[mfilename '_temp_' num2str(rand(1,1)) '.sofa']; +SOFAsave(fn,Obj); + +%% Reload the object and remove the temporary file +Obj2=SOFAload(fn); +delete(fn); + +%% Check if the user-defined variable is still there +if ~isfield(Obj2,'MyVariable'), error('Error!'); end + % check if the size is M +if ~all(size(Obj2.MyVariable)==[M 1]), error('Error!'); end + % check if it is identical to the created one +if ~all((Obj2.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj2.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% Make sure that the private variable is not there! +if isfield(Obj2,'PRIVATE'), error('Error!'); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m new file mode 100644 index 0000000000000000000000000000000000000000..4e6095731faf50a8eef000148949833aa5b822c9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m @@ -0,0 +1,108 @@ +% Convert data from SingleFreeFieldHRIR to SingleFreeFieldHRTF, +% extract a few frequency bins and save. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: plot figures as optional parameter added, figures are saved with titles (10.11.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% HRTF or DTF? +ARIfile='hrtf'; +% Which frequency bins to store? +bins=[10, 20, 50, 70]; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time +plotfigures=0; % 0: no figures; 1 show & save figures (and close others first) + +%% Load file in SimpleFreeFieldHRIR Conventions +f=filesep; +SOFAfn=fullfile(SOFAdbPath,'database','ari', [ARIfile '_' lower(subjectID) '.sofa']); + +if isfile(SOFAfn) + disp(['Loading: ' SOFAfn]); + IR=SOFAload(SOFAfn); +else + warning(['File not existing: ' SOFAfn ' --> Please download it from http://www.oeaw.ac.at/isf/hrtf and save it to: ' fullfile(SOFAdbPath,'database','ari', [ARIfile '_' lower(subjectID) '.sofa'])]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + +%% Plot figures +if plotfigures==1 + close all; + PlotFigures(IR, 'HRIR', '') +end + +%% Get a new SimpleFreeFieldTF conventions +TF=SOFAgetConventions('SimpleFreeFieldHRTF'); +disp('Converting SimpleFreeFieldHRIR to SimpleFreeFieldHRTF'); + +%% Copy variables and metadata +TFempty=rmfield(TF,fieldnames(SOFAgetConventions('SimpleFreeFieldHRTF','r'))); % skip all read-only metadata +Xf=fieldnames(rmfield(TFempty,{'API','Data'})); % skip other internal +for ii=1:length(Xf) + if isfield(IR, (Xf{ii})), TF.(Xf{ii})=IR.(Xf{ii}); end % copy if available +end + +%% Transform data +TF.Data.Real=zeros(IR.API.M,IR.API.R,length(bins)); +TF.Data.Imag=zeros(IR.API.M,IR.API.R,length(bins)); +TF.N=(bins*IR.Data.SamplingRate/IR.API.N)'; + +for ii=1:IR.API.M + cplx=fft((IR.Data.IR(ii,:,:))); + TF.Data.Real(ii,:,:)=real(cplx(:,:,bins)); + TF.Data.Imag(ii,:,:)=imag(cplx(:,:,bins)); +end + +%% Update dimensions +TF=SOFAupdateDimensions(TF); +%% Plot figures +if plotfigures==1 + PlotFigures(TF, 'HRTF', [', bins ' num2str(bins)]) +end + +%% Save +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['ARI_' ARIfile '_' subjectID '_' num2str(length(bins)) '_freqs.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn,IR,compression); + +function PlotFigures(data, type, bins) + figure; SOFAplotHRTF(data,'EtcHorizontal'); % energy-time curve in the horizontal plane (+/- THR) + tit=[type ' ETC Horizontal' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'EtcMedian'); % energy-time curve in the median plane (+/- THR) + tit=[type ' ETC Median' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'MagHorizontal'); % magnitude spectra in the horizontal plane (+/- THR) + tit=[type ' Magnitude Horizontal' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'MagMedian'); % magnitude spectra in the median plane (+/- THR) + tit=[type ' Magnitude Median' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'MagSpectrum'); % single magnitude spectrum for direction(s) DIR in COLOR +% tit=[type ' Magnitude Spectrum' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'MagSagittal'); % magnitude spectra in a sagittal plane specified by OFFSET +/- THR +% tit=[type ' Magnitude Sagittal' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'ITDhorizontal'); % ITD horizontal +% tit=[type ' ITD Horizontal' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m new file mode 100644 index 0000000000000000000000000000000000000000..af290e211e94c02bedd37e62fcded6bc515f8727 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the SimpleFreeFieldHRSOS conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SimpleFreeFieldHRSOS'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.SOS=rand(4800,2,6); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m new file mode 100644 index 0000000000000000000000000000000000000000..8db35f584dcc52c4a9e119a84e6c5cce6c0be784 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the SimpleFreeFieldSOS conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SimpleFreeFieldSOS'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.SOS=rand(4800,2,6); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m new file mode 100644 index 0000000000000000000000000000000000000000..91b10fdf6ae444f9cafecff94c79f76e000f0391 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m @@ -0,0 +1,60 @@ +% SOFA Toolbox - demo script for the convention SimpleHeadphoneIR. +% load headphone IRs from a SOFA file from the ARI headphones database + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define parameters +% Subject index of the file to convert +subjectID='NH5'; + +%% Load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'headphones', 'ari', ['hpir_' lower(subjectID) '.sofa']); +disp(['Loading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot amplitude spectra +figure; +hold on; box on; +cols='bgrmky'; + +%if ~isoctave +if exist('OCTAVE_VERSION','builtin') == 0 + if isfield(X, 'MeasurementDate') + meastime=[0; diff(X.MeasurementDate)]; % diff not working in Octave + else + meastime=diff(X.GLOBAL_DateCreated); % diff not working in Octave + end +end + +for ii=1:X.API.M + plot(20*log10(abs(fft(squeeze(X.Data.IR(ii,1,:)),X.Data.SamplingRate))),cols(ii)); + if ii>1 + % if ~isoctave; + if exist('OCTAVE_VERSION','builtin') == 0 + leg{ii}=['#' num2str(ii) ':' num2str(meastime(ii)) ' seconds later']; + else + leg{ii}=['#' num2str(ii)]; + end + end +end + +for ii=1:X.API.M + plot(20*log10(abs(fft(squeeze(X.Data.IR(ii,2,:)),X.Data.SamplingRate)))-20,cols(ii)); +end + +xlim([-200 18200]); + +axis([-200 18200 -65 15]); +leg{1}='#1, first measurement'; +legend(leg); + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m new file mode 100644 index 0000000000000000000000000000000000000000..5897b2feee3b844f811972058b9310ebd115e9da --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m @@ -0,0 +1,157 @@ +% demo for SingleRoomDRIR: save DRIR data from Uni Oldenburg (Office II) as +% SOFA file and plot the speaker and listener positions. +% It uses conventions SingleRoomDRIR and RoomType 'shoebox', defined by +% RoomCornerA and RoomCornerB. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Based on the bachelor thesis of Wolfgang Hrauda (2013). + +% Measurement situation: +% T_60 = 300 ms +% speaker positions: +% entrance, desk, desk, at window (A, B, C, D) +% conditions: +% for position A and D: door and window were open +% Listener: headorientation = {1 2} -> 0�/-90� (straight/looking over right shoulder) +% Receivers: +% ch 1 & 2: 'in-ear' IRs from in-ear microphoes (not available for Office I) +% 'bte' 6-channel BTE-IRs: +% ch 3 & 4: 'front' BTE-IRs front microphone pair +% ch 5 & 6: 'middle' BTE-IRs middle microphone pair +% ch 7 & 8: 'rear' BTE-IRs rear microphone pair +% ambient noise: telepohne, keyboard typing, ventilation (all for both +% orientations); opening and closing the door (15 times) + + +%% Define parameters + + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% --- loading Uni Oldenburg data ---- +PathO=fullfile(fileparts(SOFAdbPath), 'Oldenburg','HRIR_database_mat','hrir','office_II'); +disp(['Loading from: ' PathO filesep]); + +A1fn = [PathO filesep 'office_II_1_A.mat']; +B1fn = [PathO filesep 'office_II_1_B.mat']; +C1fn = [PathO filesep 'office_II_1_C.mat']; +D1fn = [PathO filesep 'office_II_1_D.mat']; +A2fn = [PathO filesep 'office_II_2_A.mat']; +B2fn = [PathO filesep 'office_II_2_B.mat']; +C2fn = [PathO filesep 'office_II_2_C.mat']; +D2fn = [PathO filesep 'office_II_2_D.mat']; + +% has dimension: N x R +if isfile(A1fn); A1 = load(A1fn); else, error(['File not existing: ' A1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); B1 = load(B1fn); else, error(['File not existing: ' B1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); C1 = load(C1fn); else, error(['File not existing: ' C1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); D1 = load(D1fn); else, error(['File not existing: ' D1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); A2 = load(A2fn); else, error(['File not existing: ' A2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); B2 = load(B2fn); else, error(['File not existing: ' B2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); C2 = load(C2fn); else, error(['File not existing: ' C2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); D2 = load(D2fn); else, error(['File not existing: ' D2fn ' --> Please download it to: ' PathO filesep]); end +% +% B1 = load([PathO filesep 'office_II_1_B.mat']); +% C1 = load([PathO filesep 'office_II_1_C.mat']); +% D1 = load([PathO filesep 'office_II_1_D.mat']); +% A2 = load([PathO filesep 'office_II_2_A.mat']); +% B2 = load([PathO filesep 'office_II_2_B.mat']); +% C2 = load([PathO filesep 'office_II_2_C.mat']); +% D2 = load([PathO filesep 'office_II_2_D.mat']); + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SingleRoomDRIR'); + +%% Listener and Receiver +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 9; ... % in-ear + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % front bte + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % middle bte + 0.02 0.09 0.02; 0.02 -0.09 0.02]; % rear bte +Obj.ListenerPosition = [2.16 4.4 1.1]; +Obj.ListenerUp = [0 0 1]; +Obj.ListenerView = [repmat([1 0 0],4,1); repmat([0 -1 0],4,1)]; + +%% Source and Transmitter + +Obj.EmitterPosition = [0 0 0]; +A = [0.52 5.27 1.8]; +B = [0.79 1.25 1.1]; +C = [2.52 1.23 1.1]; +D = [2.38 0 1.8]; +Obj.SourcePosition = [A; B; C; D; A; B; C; D;]; +Av = [-1 0 0]; +Bv = [1 0 0]; +Cv = [1 0 0]; +Dv = [1 0 0]; +Obj.SourceView = [Av; Bv; Cv; Dv; Av; Bv; Cv; Dv;]; +Obj.SourceUp = [0 0 1]; + +%% Fill Data with data +% change data matrix dimension: N x R -> M x R x N +A1.data = shiftdim(A1.data,1); +data(1,:,:) = A1.data; +B1.data = shiftdim(B1.data,1); +data(2,:,:) = B1.data; +C1.data = shiftdim(C1.data,1); +data(3,:,:) = C1.data; +D1.data = shiftdim(D1.data,1); +data(4,:,:) = D1.data; +A2.data = shiftdim(A2.data,1); +data(5,:,:) = A2.data; +B2.data = shiftdim(B2.data,1); +data(6,:,:) = B2.data; +C2.data = shiftdim(C2.data,1); +data(7,:,:) = C2.data; +D2.data = shiftdim(D2.data,1); +data(8,:,:) = D1.data; +Obj.Data.IR = data; +Obj.Data.Delay = zeros(1,size(Obj.Data.IR,2)); +Obj.Data.SamplingRate = A1.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'HATS'; +Obj.GLOBAL_History='Converted from the Uni Oldenburg database'; +Obj.GLOBAL_License='http://medi.uni-oldenburg.de/hrir/html/download.html'; +Obj.GLOBAL_References='H. Kayser, S. D. Ewert, J. Anem�ller, T. Rohdenburg, V. Hohmann, and B. Kollmeier, "Database of Multichannel In-Ear and Behind-the-Ear Head-Related and Binaural Room Impulse Responses," EURASIP Journal on Advances in Signal Processing, vol. 2009, doi:10.1155/2009/298605'; + +%% Setup the room +Obj.GLOBAL_RoomType='shoebox'; +Obj.GLOBAL_RoomDescription='Office II at the University of Oldenburg, T_60 = 300 ms'; + +Obj.RoomCornerA = [0; 0; 0]; +Obj.RoomCornerA_Type = 'cartesian'; +Obj.RoomCornerA_Units = 'meter'; +Obj.API.Dimensions.RoomCornerA='C'; + +Obj.RoomCornerB = [3.3; 6; 0]; +Obj.RoomCornerB_Type = 'cartesian'; +Obj.RoomCornerB_Units = 'meter'; +Obj.API.Dimensions.RoomCornerB='C'; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','Oldenburg_OfficeII.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); +clear Obj; + +%% Re-load the file +disp(['Reloading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot the 2D-plan of the measurement setup +SOFAplotGeometry(X); +title('Office II from Kayser et al. (2009) saved as SingleRoomDRIR'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..526efa265573bc73d5bb14d95c96d18cefaa566d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m @@ -0,0 +1,115 @@ +% Demonstrates the usage of SingleRoomMIMOSRIR. +% Idea: demo_SingleRoomMIMOSRIR loads SRIRs from IEM database, +% converts to SH as SingleRoomMIMOSRIR, does planewave decompositon, and stores +% the data as a .sofa file. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: bugs fixed regarding variables ReceiverDescriptions and EmitterDescriptions; source files folder moved to data directory; some minor fixes (03.08.2022) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Data +% https://phaidra.kug.ac.at/view/o:104376, LS: 3 oder 5 +% documentation: https://www.mdpi.com/2076-3417/10/11/3747 + +% Download IR dataset from https://phaidra.kug.ac.at/view/o:104376 +% Copy the folder 'IEM' to your data directory + +Obj = SOFAgetConventions('SingleRoomMIMOSRIR'); +Obj.GLOBAL_Title = 'LigetiHall_CubeletToSt450'; +Obj.GLOBAL_Organization = 'Institut für elektronische musik und akustik, Graz, Austria'; +Obj.GLOBAL_AuthorContact = 'julien.demuynke@eurecat.org, markus.zaunschirm@atmoky.com, zotter@iem.at'; +Obj.GLOBAL_References = 'Auralization of High-Order Directional Sources from First-Order RIR Measurements (2020)'; +Obj.GLOBAL_Comment = '1rst order RIR measurements with Cubelet loudspeaker array protoype (6 loudspeakers) and TSL ST450 microphone (4 channels) in the György Ligeti Saal, Graz, Austria. The source was surrounded by 4 reflecting baffles (0.9 x 1.8 m) in its rear halfspace.'; +Obj.GLOBAL_ListenerShortName = 'TSL ST450'; +Obj.GLOBAL_SourceShortName = 'Cubelet loudspeaker array protoype'; +Obj.GLOBAL_DatabaseName = 'IEM'; +Obj.GLOBAL_ListenerDescription = ' 4-channel Ambisonic B-format microphone array with r = 2 cm'; +Obj.GLOBAL_SourceDescription = ' Spherical (r = 7.5 cm) 6-channel loudspeaker array prototype with loudspeakers arranged on surfaces of a cube'; +Obj.GLOBAL_RoomDescription = 'György-Ligeti Room in building LG14 - MUMUTH in Universität für Musik und darstellende Kunst Graz, Austria. Shoebox shaped room of surface 511.15m2 and volume 5630m3 with floor made of wooden panels'; + +Obj.ReceiverPosition_Type = 'spherical harmonics';%B-format +Obj.EmitterPosition = [0 0 0.075;90 0 0.075;180 0 0.075;270 0 0.075;0 90 0.075;0 -90 0.075]; +Obj.SourcePosition = [4.2 0 0]; +Obj.SourceView = [-1 0 0];%The source and the listener are facing each other + +datapath=[fileparts(SOFAdbPath) filesep 'IEM' filesep]; +IR_list = dir([datapath '*.wav']); +if isempty(IR_list) + error([' Folder does not exist or is empty: ' strrep(datapath,['SOFA' filesep '..' filesep],'') newline ' Download IR dataset from https://phaidra.kug.ac.at/view/o:104376 and save the files to the folder ''IEM'' in your data directory.']) +end +IR_INFO = audioinfo([IR_list(1).folder filesep IR_list(1).name]); + +C = 3; +I = 1; +M = 1; +R = IR_INFO.NumChannels; +N = IR_INFO.TotalSamples; +E = length(IR_list); + +fs = IR_INFO.SampleRate; +Obj.Data.IR = zeros(M,R,N,E); +for i = 1:6 + IR = audioread([IR_list(i).folder filesep IR_list(i).name]); + Obj.Data.IR(1,:,:,i) = transpose(IR); +end +Obj.Data.SamplingRate = fs; +Obj.Data.Delay = zeros(M,R,E); + +Obj.ReceiverView = zeros(R,C,I); +Obj.ReceiverUp = zeros(R,C,I); +Obj.EmitterView = zeros(E,C,I); +Obj.EmitterUp = zeros(E,C,I); + +% Add ReceiverDescriptions as string array +str={}; +for ii=1:R + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +Obj = SOFAaddVariable(Obj,'ReceiverDescriptions','RS',str); + +% Add EmitterDescriptions as string array +str={}; +for ii=1:E + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +Obj = SOFAaddVariable(Obj,'EmitterDescriptions','ES',str); + +Obj = SOFAupdateDimensions(Obj); + +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','LigetiHall_CubeletToSt450_IRs.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); + +% +% Paper for the algorithms: +% Park, M. and Rafaely, B. (2005). "Sound-field analysis by plane-wave decomposition using spherical microphone array," +% JASA, 118, 3094 3103. https://doi.org/10.1121/1.2063108 + + +%% Story line... +% First, the coefficients pnm up to order N are calculated using Eq. 5, + +% pnm = sum j=1 to M, a_j p(omega_j) Yn m_j. + + +% and then the waves directional amplitude +% density at each frequency, i.e., plane-wave decomposition, is +% computed at the desired directions using Eq. 9. +% +% b_n (kr,ka) = 4pi i^n(j_n(kr) ? ...) Eq. 7 +% +% w (omega_l) = sum n=0 to N sum m=?n to n p_nm / b_n Y (omega_l) + +% to be saved: p_nm and b_n(kr,ka) or simple a. +% + +%% Also this might help: Khaykin, D. and Rafaely, B. (2012). "Acoustic analysis by spherical +% microphone array processing of room impulse responses," JASA, 132, 261�270. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..448b5e1840a604ee48c558f3d63078039da53656 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m @@ -0,0 +1,49 @@ +% Demonstrates the usage of the SingleRoomSRIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SingleRoomSRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.IR=rand(4800,1); +Obj.ListenerPosition=zeros(4800,3); Obj.ListenerPosition(:,1)=1; +Obj.SourcePosition=zeros(4800,3); Obj.SourcePosition(:,2)=1; + +% Add ReceiverDescriptions as string array +str={}; +for ii=1:Obj.API.R + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +Obj = SOFAaddVariable(Obj,'ReceiverDescriptions','RS',str); + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..58ce22adf7e6eabd7ee456bb6df95d0047691069 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m @@ -0,0 +1,62 @@ +% SOFA Toolbox - demo script + +% load HRTF in TU Berlin format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Prefix to the files +TUBfile = 'QU_KEMAR_anechoic_'; +% Define vector with radii to be loaded. Available files: 0.5, 1, 2, and 3 m +% radius=[0.5 1 2 3]; +radius=[0.5]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load, convert, and save the requested TU-Berlin files +for ii=1:length(radius) + % load + + TUBfn=fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR', [TUBfile num2str(radius(ii)) 'm.mat']); + + if isfile(TUBfn) + disp(['Loading: ' TUBfn]); + TUB=load(TUBfn); + else + if radius(ii) == 0.5 % catch if file name ends with "05m.mat" instead of "0.5m.mat" + TUBfn2=fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR', [TUBfile '05m.mat']); + if isfile(TUBfn2) + disp(['Loading: ' TUBfn2]); + TUB=load(TUBfn2); + else + warning(['File not existing: ' TUBfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR')]); + error(['Sorry.... ' mfilename ' cannot complete!']); + end + else + warning(['File not existing: ' TUBfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR')]); + error(['Sorry.... ' mfilename ' cannot complete!']); + end + end + + % convert and add application specific metadata + Obj=SOFAconvertTUBerlin2SOFA(TUB.irs); + Obj.GLOBAL_DatabaseName = 'TU-Berlin'; % maybe setting the name by function parameter + Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; + Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + Obj.GLOBAL_Organization = 'Technische Universit�t Berlin'; + Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; + % save + SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['TU-Berlin_' TUBfile 'radius_' sprintf('%g',radius(ii)) 'm.sofa']); + disp(['Saving: ' SOFAfn]); + Obj=SOFAsave(SOFAfn, Obj, compression); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/helpers/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/helpers/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..07054edbe87c5e92fed84549e985192dcb35905e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/helpers/readme.txt @@ -0,0 +1 @@ +this folder is prepared for third-party helper files and folders \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/history.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/history.txt new file mode 100644 index 0000000000000000000000000000000000000000..76a25d3a76277300a4ceb411cfe130e9b2fa2709 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/history.txt @@ -0,0 +1,363 @@ +************************************************************* +*** History of SOFA Toolbox for Matlab and Octave +*** Acoustics Research Institute, Austrian Academy of Sciences, Vienna +*** Project leader: Piotr Majdak, piotr.majdak@oeaw.ac.at +*** Contributors: +*** Michael Mihocic +*** Harald Ziegelwanger +*** Hagen Wierstorf +*** Wolfgang Hrauda +*** Fabian Brinkmann +*** Felix Perchfler +************************************************************* + +*** DEVELOPMENT STATUS *** + +*** v2.1 (first 2.x release) + + +*** v2.0 (not released, rebranded to SOFA Toolbox) + +## Rebranding ## +- main directory renamed to "SOFAtoolbox" +- repository renamed to "SOFAtoolbox" +- subfolder "HRTFs" renamed to "data"; some files adapted +- all SOFA files created by demo_ will be saved in sofatoolbox_test + +## Core Functionality ## +- .gitignore added, updated multiple times +- Support for spherical harmonics added. +- SOFAconvertCoordinates.m: type horizontal-polar removed (not (properly) defined in SOFA) +- SOFAarghelper: minor bugs fixed (changes FB) +- SOFAinfo: showing all global mandatory fields now, plus some more for SimpleFreeFieldHRIR +- demoPlaySound.m added +- Readme.md: Example fixed (demoPlaySound.m) +- headers of functions checked, updated, author format changed to machine-readable format (#author) +- NETCDFload: 'deblank' command added when loading strings to avoid trailing empty spaces in size of array dimension +- SOFAcalculateITD.m added, adapted from AMT itdestimator +- SOFAcalculateLFE.m added (by DC), db changed to mag2db (Octave support) +- SOFAstart: + - Bug fixed when using 'restart' option: SOFAdbPath and SOFAdbURL were not reset + - Bug in help comment fixed + - flag 'full' added: show all information, including all compiled conventions & versions + - changed order of display output messages ((c) first) + - Bug fixed when adding paths (added at bottom in some specific cases) + +## Toolbox Functionality +- Conventions: + - Conventions for SOFA 2.0 added + - SOFAgetConventions: Versioning of convention files .CSV added + - csv files renamed to always include SOFAConventionsVersion in file name (created .mat files are unaffected) + - FreeFieldDirectivityTF_1.0.csv: + - updated by David Ackermann (not sure if ReceiverPosition and EmitterPosition still need to be updated) + - Mandatory flag removed for: Global:Comment, ListenerUp, ListenerUp:Type, ListenerUp:Units + - Dimension of ReceiverPosition and EmitterDescription fixed + - FreeFieldHRTF_1.0.csv: GLOBAL:SOFAConventionsVersion version number fixed + - SingleRoomSRIR_1.0.csv: GLOBAL:SOFAConventionsVersion version number fixed, RoomCornerA, RoomCornerB, RoomCorners:Type, RoomCorners:Units: Mandatory flag removed + - Dimension of Data.SamplingRate fixed to "I, M" for: GeneralFIR-E_2.0.csv, GeneralFIR_2.0.csv, General_1.0.csv, SimpleFreeFieldHRIR_1.0.csv, SimpleFreeFieldHRSOS_1.0.csv, SimpleHeadphoneIR_1.0.csv, SingleRoomSRIR_1.0.csv + - Conventions2Wiki.m: Column headers flags and dimensions changed to a hyperlink linking to that corresponding part on the website + - several bugs fixed; non-ASCII quotes replaced by ' (changes FB) + - Conventions FreeFieldHRIR_1.0.csv added + - SOFAcompileConventions: + - ignores files beginning with '_' + - Bug fixed when running in Octave + - '10' replaced by 'newline' in strings to avoid warnings in Octave + - display messages changed to output variable dispOutput + - bug fixed: replaced version "2" by "2.0" to keep one minor digit everywhere + - flags fixed +- Demos: + - demo_FreeFieldHRTF.m added; updated several times, allows saving figures as fig & png (see parameter 'savefigures'), some bug fixes + - demo_FreeFieldDirectivityTF.m: adapted to actual data on sofaconventions.org -> working now; plot_trumpet_directivity included + - SOFAconvertMIT2SOFA.m, demo_FHK2SOFA.m, demo_SingleRoomDRIROldenburg.m, demo_SingleRoomMIMOSRIR.m, demo_TUBerlin2SOFA.m: error message if source files are not available + - demo_ARI2SOFA.m, demo_LISTEN2SOFA.m: bug fixed: subject_ID was always overwritten; error message if source files are not available + - demo_SimpleFreeFieldHRIR2TF.m: bug fixed: Object to be saved was wrong; error message if source files are not available; updated several times; parameter 'plotfigures' causes plotting all figures, and saving them (fig, png) if set to 1 + - demo_SimpleHeadphoneIR.m: if .MeasurementDate is not existing use .GLOBAL_DateCreated as measurement time (legend in figure) + - SOFAconvertSCUT2SOFA.m: bug fixed when source files are not available -> error message + - demo_BTDEI2SOFA.m: Minor bug fixed in error message text + - demo_SOFAcalculateITD.m added + - demo_SOFAcalculateLFE.m added (by DC) + - demo_SphericalHarmonicsMic added +- test_SOFAall.m: + - structured (first *->SOFA, then SOFA->*, then SOFA functions, then SOFA conventions), and sorted (alphabetically) + - missing demos added + - disp messages improved + - some bugs fixed; all conventions are included in at least one demo file; all demos are tested with Matlab & Octave (run test_SOFAall.m) + - Matlab: all demos are working in Matlab, without any visible warnings + - Octave: all demos are working without any errors except for FHK2SOFA (not working at all; skipped in Octave), and some minor restrictions cause by unsupported commands, see warning messages during process for details + - some bugs fixed; demos that require souce files that are not publicly available will be catched with a warning instead of an error +- Download links updated for: + - HRTFs\ARI\readme.txt + - HRTFs\CIPIC\readme.txt + - HRTFs\TU-Berlin KEMAR\readme.txt +- SOFAplotHRTF: + - 'convert' flag added -> 1: convert to FIR and then to TF domain. Can be set to 0 if data is available in TF domain (FreeFieldDirectivityTF, GeneralTF, SimpleFreeFieldHRTF conventions). By default the function chooses the best option. + - type 'ITDhorizontal' added (changes DC) + - Octave support (except for type itdhorizontal) + - dependency on function 'npi2pi' removed (required toolbox in Matlab; in Octave not supported; outdated anyway) + - keyvalue 'R'/'r' renamed to 'receiver' + - Obj.GLOBAL_Title only displayed in figure title if not empty; title handling improved +- SOFAplotGeometry: + - bug fixed when extracting LU (listener up) coordinates + - minor bugs fixed +- headers of functions checked, updated, author format changed to machine-readable format (#author) +- helper folder renamed to helpers; folder is prepared for downloadable third-party functions +- helper functions removed; some functions are already supported by MATLAB, a few functionalities were implemented in the files themselves +- isoctave.m removed, replaced by code in files +- miro.m removed from repository; class file is downloaded if needed (by demo_FHK2SOFA, SOFAconvertFHK2SOFA, SOFAconvertTHK2SOFA); file might also be included in other toolboxes and can be used from them + +## TO-DO ## +- SOFAplotGeometry: complete rewrite with extensive support +- SOFAplotGeometry shows a cloud for spatially continuous emitters and receivers + + +************************************************************************************************************ + + +*** v1.1.2 +- SOFAplotGeometry: bug fix if no SourceView given +- FreeFieldDirectivityTF: missing eCM in EmitterPosition fixed +- SOFAcheckFilename: do not convert if filename is http:// +- SOFAplotHRTF: plot TF with regular frequency grid. Not tested for irregular grids, though... + +*** v1.1.1 +- SOFAstart: bug fix when starting for the first time +- SOFAconvertTUBerlinBRIR2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertTHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertFHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAappendText.m: example added to help +- SOFAcompileConventions: fix for changes in Octave 4.2 +- FreeFieldDirectivityTF: updated to version 0.2 + +*** v1.1.0 (not released) +- SOFAremoveVariable added. It removes a variable from the SOFA object. +- SOFAplotGeometry: show SourceView, and bug fix ListenerView. +- SOFAdbPath, SOFAdbURL: reset the path/URL to the default if the parameter is 'reset'. +- SOFAhrtf2dtf: handling for R=1 added. +- SOFAfind added: Find an index for a given position (draft, to be improved). +- SOFAload: provide error message on loading unknown conventions + +*** v1.0.4 (29.4.2019) +- on "SOFA upgrade warning", display a message on how to switch it off +- SOFAplotHRTF: 'magsagittal' added to plot HRTFs along a sagittal plane. +- SOFAload can use filenames beginning with "db://" to indicate to load from the database (local or remote) +- SOFAstart avoids repeated starts now - + - once SOFAstart has been started, SOFAstart won't be executed fully again, when the paths are still available. + - Call SOFAstart('restart') if a restart needs to be forced. + + +*** v1.0.3 (5.9.2018) +- automatic load of the netcdf package in Octave on SOFAstart +- SOFAspat: bugs in normalization, actual position selection removed +- SOFAhrtf2dtf: RMS and weighted averaging added, Octave compatibility ensured +- SOFAcompileConventions: bug fix when compiling conventions in Octave 4.2.1 +- test_SOFAall: suppress irrelevant warnings +- SOFAconvertMIT2SOFA: wavread replaced by audioread +- SOFAconvertConventions: it can convert from SimpleFreeFieldTF to SimpleFreeFieldHRIR. +- SOFAplotHRTF: more variable input of parameters, normalization optional +- SOFAconvertTHK2SOFA: converter from THK format (in miro format) to SOFA added. + +*** v1.0.2 (16.8.2016) +- SOFAplotHRTF: extended to SimpleFreeFieldTF and some cases of GeneralTF +- SOFAplotGeometry: extended to SimpleFreeFieldTF +- SOFAconvertTUBerling2SOFA: uses MultiSpeakerBRIR now +- SOFAspat, SOFAcalculateAPV: minor bug fixes + +*** v1.0.1 (10.6.2015) +- miro class is not supported in Octave. Error is thrown in demo_FHK2SOFA and converterFHK2SOFA +- demo_BTDEI2SOFA: bug fix in renamed BTDEI files +- demo_SOFA2ARI: bug fix in coordinate comparison + +*** v1.0.0 (3.6.2015) +- 'short' flag added to SOFAstart in order to show only a short header on start-up. +- warnings are function-specific now and can be specifically enabled/disabled. + +*** v0.9.1 (13.5.2015) +- 0.9.1 is the internal numbering for the release version 1.0 RC2 +- SimpleFreeFieldSOS added +- SOFAexpand and SOFAaddVariable handle Data. variables now +- SOFAplotHRTF supports SimpleFreeFielsSOS now + +*** v0.9.0 (12.5.2015) + +- 0.9.0 is the internal numbering for the release version 1.0 RC1 +- update of all conventions to SOFA 1.0 +- changes according to the AES212-standard implemented +- Octave: upgraded to a new netcdf-package: http://modb.oce.ulg.ac.be/mediawiki/index.php/Octave-netcdf +- Matlab/Octave: NETCDF* functions merged for both systems (thx to Hagen Wierstorf) +- HRTFs directory: database handling improved: + - SOFAdbPath mirrors http://sofacoustics.org/data now. + - Warning: directory structure of HRTFs/SOFA changed! + - all SOFA files created by demo_ will be saved in sofa_api_mo_test + - all demo_ files which use SOFA files will be automatically downloaded from sofacoustics.org +- clean up of comments +- SOFAcalculateAPV: reimplemented +- horsph and sph2hor: bug fixes +- directory CDL deleted (had historical relevance only) +- SOFAdefinitions: flag 'units' added for unit aliases. +- SOFAgetConventions: returns empty vector if conventions not supported + +*** v0.4.4 (until 20.4.2015) unreleased + +*** v0.4.3 (5.6.2014) by Piotr Majdak +- fix: annoying bug in SOFAupgradeConventions + +*** v0.4.2 (7.4.2014) by Piotr Majdak +- fix: SOFAhrtf2dtf supports more than two receivers + +*** v0.4.1 (30.3.2014) by Piotr Majdak +- MultiSpeakerBRIR conventions added +- SOFAcompact: compacts variables along dimensions, opposite to SOFAexpand. Functionality not complete for 3D variables +- SOFAcompare: compares two SOFA objects. Preliminary functionality; compares attributes only +- SOFAexpand: expanding of Data added +- bug fix: SOFAplotGeometry +- function-specific warnings added: SOFA:upgrade and SOFA:save +- SOFAload optimized for handling huge (3.7 GB) data files on a 4 GB RAM machine + + +*** v0.4 (19.3.2014) by Piotr Majdak +- implements SOFA 0.6: + - GLOBAL_Source renamed to GLOBAL_Origin + - GLOBAL_TimeCreated and GLOBAL_TimeModified renamed to GLOBAL_DateCreated and GLOBAL_DateModified, respectively + - If ListenerUp is provided, ListenerView must be provided as well. If ListenerView is provided, ListenerView_Type and ListenerView_Units must be provided as well. This also applies to Source, Emitter, and Receiver objects. + - Geometry: only "cartesian" or "spherical" coordinate systems allowed + - In SimpleFreeFieldHRIR: GLOBAL_SubjectID renamed to GLOBAL_ListenerShortName +- Converters adapted to provide more precise information +- SOFAappendText added for appending a text to an attribute +- SOFAdefinitions: returns various definitions, depending on the input flag +- SOFAupgradeConventions: upgrades conventions up to 0.6 now. + +*** v0.3.1 (2.9.2013) by Piotr Majdak +- zip file required 7-zip, fixed +- minor bug fixes + +*** v0.3.0 (27.8.2013) by Piotr Majdak +- major change: .API added to the structure, contains .Dimensions and the dimension sizes (formely known as .DimSize) +- implements SOFA 0.5 (without the support for string arrays) +- upgrade of SimpleFreeFieldHRIR 0.3 and other conventions +- syntax of convention files .csv adapted to that from the specs ("_" replaced by ":") +- SOFAcalculateAPV added, provides calculation of the apparent position vector (APV) +- SOFAplotGeometry added, rudimentary plotting available for SimpleFreeFieldHRIR and SingleRoomDRIR +- SOFAaddVariables supports private variables now + +*** v0.2.9 (30.5.2013) by Piotr Majdak +- development snapshot for the draft of SOFA 0.4 +- tested for Matlab (Octave support not finished yet) +- conventions implemented as CSV files which are compiled to MAT at start and are cached by SOFAgetConventions +- user-defined HRTF database path +- seemless download of remote SOFA files on SOFAload +- user-defined HRTF internet repository +- seemless upgrade from SOFA 0.3 files on SOFAload + +*** v0.2.1 (13.5.2013) by Piotr Majdak +- Bug fix with the wrong spelling of "License" +- "License" it very restrictive per default now +- demo_SOFAsave included + +*** v0.2.0 (2.5.2013) by Piotr Majdak +- Updated to SOFA 0.3 +- Octave support added +- demo_* create file names compliant with MS DOS FAT character set +- test script (test/test_SOFAall.m) added +- converters do not add database specific attriubutes, this is done in demo_* +- new demos: SOFAmerge, SOFAload, SOFAsave +- readme improved +- Pulse.sofa removed as binary, it can be created with demo_SOFAsave now +- Link to HRTF files saved as SOFA added (nice for playing around) + +*** v0.1.4 (2.5.2013) by Piotr Majdak +- Major bug fix: dimension order reversed while loading/saving in Matlab +- Some other minor issues closed +- Ready for intercompatibility test between Matlab and Octave + +*** v0.1.3 (18.4.2013) by Piotr Majdak +- This version implements SOFA specs version 0.2 with the following limitations: + - no Octave support + - only SimpleFreeFieldHRIR supported and tested + +- Detailed changes: + - directory structure changed + - new converter added: SOFA2ARI + - SOFAdbPath added + +*** v0.1.2 (17.4.2013) by Piotr Majdak +- SOFAload: partial loading added. Load of metadata only or by measurement section +- docs: changes since AES2013-specs added. +- history file moved to docs +- Repository cleaned from older stuff + +*** v0.1.1 (16.4.2013) by Piotr Majdak +- SOFAload improved: checks added. Still further checks would be nice, but it can be used now. +- SOFAsave improved: saves user-defined variables +- SOFAexpand added: expands the singleton dimensions in the SOFA object +- Convertors for MIT KEMAR, LISTEN, and CIPIC databases added (with corresponding demos) +- HRTF directory created where all HRTFs should be stored. The convertors rely on that. +- SOFAspat improved, now the engine works better + +*** v0.1.0 (11.4.2013) by Piotr Majdak +- Saving/Loading works in Matlab, it is quite rudimentary now: + - Data and Variables saved as Double + - No string in variables supported yet + - One Conventions implemented and tested (SingleFreeFieldHRIR) + - Loading: no checks (todo) + - Saving: removes optional variables (bug) + - No partial loading/saving yet +- Convertion: ARI2SOFA with demo_ARI2SOFA added +- Spatialization: very rudimentary demo added (SOFAspat and demo_SOFAspat), just for fun + +*** v0.0.12 (12.3.2013) by Piotr Majdak +- Conventions: transmitter renamed to emitter + +*** v0.0.11 (7.3.2013) by Piotr Majdak +- Conventions added +- Octave branch deleted +- Examples: ARI2SOFA as a function +- General: adapted to current specs. Don't use yet. + +*** v0.0.10 (5.3.2013) by Piotr Majdak +- ARI2SOFA: changed to a function now, the fields are more clear defined +- SOFAsave: transmitted and receiver separated, dimensions changed +- Specs have drastically changed - beware of using this version at the current development state + +*** v0.0.9 (31.1.2013) by Piotr Majdak +- included octave part from Hagen Wierstorf +- changed the data structure format +- added try-catch to SOFAsave to avoid open file handles + +*** v0.0.8 (24.08.2012) by Wolfgang Hrauda +- changed data structure format +- updates and fixes in several functions and scripts +- added Eigenmike.sofa as a demo file + +*** v0.0.7 (23.08.2012) by Wolfgang Hrauda +- now using structures or cells as input and output values of functions +- added and renamed several functions and scripts +- updates in several functions and scripts + +*** v0.0.6 (14.08.2012) by Wolfgang Hrauda +- added new functions for coordinate type conversion +- functionality of SOFAgetData slightly expanded +- dismissed function SOFAloadVariables (is now an option in SOFAload) +- "ARI_to_SOFA_lab_setup" updated +- minor fixes in several functions + +*** v0.0.5 (08.08.2012) by Wolfgang Hrauda +- implemented additional dimensions for string variables in SOFAsave +- added new function SOFAloadVariables (a variant of SOFAload) +- added new demo script "ARI_to_SOFA_lab_setup" +- fixes in several functions + +*** v0.0.4 (07.08.2012) by Wolfgang Hrauda +- fixed some issues in SOFAsave +- minor changes in SOFAload +- added new functions SOFAgetID, SOFAgetData, SOFAlistVariables + +*** v0.0.3 (03.08.2012) by Wolfgang Hrauda +- split demo script in two API functions and one script that calls them +- change file extension to 'sofa' + +*** v0.0.2 (01.08.2012) by Wolfgang Hrauda +- finished matrix dimension check + +*** v0.0.1 (31.07.2012) by Wolfgang Hrauda +- demo script that loads ARI .mat file, converts it to SOFA format and writes to .nc-file + then reads all data from .nc.file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m new file mode 100644 index 0000000000000000000000000000000000000000..cecca186bd868f8e57cdd7c8755ae5b2dfb374fc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m @@ -0,0 +1,18 @@ +function [] = NETCDFdisplay(filename) +%NETCDFDISPLAY +% [] = NETCDFdisplay(filename) displays information about specified SOFA file + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function netcdf/NETCDFdisplay +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +ncdisp(filename); + +end %of function diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m new file mode 100644 index 0000000000000000000000000000000000000000..0aa1514c1527747558416da60b1bd5b723fec213 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m @@ -0,0 +1,154 @@ +function [Obj,Dims] = NETCDFload(filename,flags,varargin) +%% NETCDFLOAD +% Obj = NETCDFload(filename,'all') reads the SOFA object OBJ with all data from a SOFA file. +% +% Obj = NETCDFload(filename,'nodata') ignores the data, reads variables. +% +% Obj = NETCDFload(filename,[START COUNT],partialDim) reads only COUNT number of data +% in dimension partialDim (given as string) beginning with the index START. If START +% and COUNT are column vectors, then partialDim has to be a string containing the +% dimension for every column entry. +% +% [Obj,Dims] = NETCDFload(...) returns the dimension variables found in +% the file as a string. + +% #Author: Piotr Majdak: String array support. Works for 1D and 2D strings only. (10.08.2014) +% #Author: Michael Mihocic: 'deblank' command added when loading strings to avoid trailing empty spaces in size of array dimension (14.10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +%% SOFA Toolbox - function netcdf/NETCDFload +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob = 'GLOBAL_'; +globid = netcdf.getConstant('GLOBAL'); + +%% --------------------------- N E T C D F load -------------------------- +% Open the NETCDF file +try + var = 'opening file'; + ncid = netcdf.open(filename,'NC_NOWRITE'); % open file + var = 'inquirying data'; + [numdims,numvars,numglob] = netcdf.inq(ncid); % get number of anything + + % ----- GLOBAL ATTRIBUTES -------------------------------------------- + for ii=0:numglob-1 + var = netcdf.inqAttName(ncid,globid,ii); + Obj.([glob var]) = netcdf.getAtt(ncid,globid,var); + end + + % ----- DIMENSIONS --------------------------------------------------- + dimids = netcdf.inqDimIDs(ncid); + dims = cell(numdims,1); % cell array with dimension names + startp = zeros(numdims,1); % vector with start of a dimension + countp = zeros(numdims,1); % vector with the element count in a dimension + for ii=0:numdims-1 + [var,len] = netcdf.inqDim(ncid,dimids(ii+1)); + Obj.API.(var) = len; + dims{ii+1} = var; + startp(ii+1) = 0; + countp(ii+1) = len; + end + Dims = cell2mat(dims)'; + + % Check the requested measurements + if isnumeric(flags) + partialDimRange = flags; + partialDim = varargin{1}; + for ii=1:length(partialDim) + if Obj.API.(partialDim(ii))<(sum(partialDimRange(ii,:))-1) + error('Requested indices exceed measurement count'); + end; + startp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,1)-1; + countp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,2); + end + end + + + % ----- VARIABLES + ATTRIBUTES --------------------------------------- + varids = netcdf.inqVarIDs(ncid); + for ii=0:numvars-1 + [var,~,vardimids,natts] = netcdf.inqVar(ncid,varids(ii+1)); + % Data + if strfind(var,'Data.'), + if ~strcmp(flags,'nodata') + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.Data.(var(6:end))=dim; + if strfind(dim,'S') % strings + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.Data.(var(6:end))=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.Data.(var(6:end))(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.Data.(var(6:end))=deblank(cellstr(reshape(reshape(data,1,[]),size(data,2),[]))); + end + elseif length(dim)>1 + Obj.Data.(var(6:end))=permute(netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)), length(dim):-1:1); + else + Obj.Data.(var(6:end))=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + end + end + % Variables + else + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.(var)=dim; + if strfind(dim,'S') + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.(var)=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.(var)(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.(var)=deblank(cellstr(reshape(reshape(data,1,[]),size(data,2),[]))); + end + elseif length(dim)>1 + Obj.(var)=permute(data, length(dim):-1:1); + else + Obj.(var)=data; + end + end + + if natts + for jj=0:natts-1 + att = netcdf.inqAttName(ncid,varids(ii+1),jj); + attval = netcdf.getAtt(ncid,varids(ii+1),att); + if strfind(var,'Data.'), Obj.Data.([var(6:end) '_' att])=attval; else Obj.([var '_' att])=attval; end + end + end + end + +catch ME + if exist('ncid','var'); netcdf.abort(ncid); end; + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message 10 'See also the error stack before']); +end + +netcdf.close(ncid); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m new file mode 100644 index 0000000000000000000000000000000000000000..7ddc4223ebdb5d2a076e89100c3c365a26f43816 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m @@ -0,0 +1,178 @@ +function NETCDFsave(filename,Obj,Compression) +%NETCDFSAVE +% NETCDFsave(filename,Dataset,Compression) saves all data and metadata to a SOFA file. + +% SOFA Toolbox - function netcdf/NETCDFsave +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% #Author: Piotr Majdak (09.04.2013) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob='GLOBAL_'; +% Dims='IRENMCQ'; % dimensions + +globid=netcdf.getConstant('GLOBAL'); + +try + var='file creation'; + mode = netcdf.getConstant('NETCDF4'); +% mode = netcdf.getConstant('clobber'); +% mode = bitor(mode,netcdf.getConstant('CLASSIC_MODEL')); + ncid = netcdf.create(filename,mode); + +%% Save global attributes + f=fieldnames(Obj); + + for ii=1:length(f) + if ~isempty(strfind(f{ii},glob)) + var=f{ii}; + netcdf.putAtt(ncid,globid,var(strfind(var,glob)+length(glob):end),Obj.(var)); + end + end + +%% Define dimensions + + Dims=cell2mat(fieldnames(rmfield(Obj.API,'Dimensions'))'); + dimid=nan(size(Dims)); + dimsize=nan(size(Dims)); + for ii=1:length(Dims) + var=Dims(ii); + dimid(ii) = netcdf.defDim(ncid,Dims(ii),Obj.API.(var)); + dimsize(ii)=Obj.API.(var); + end + Sdim=strfind(Dims,'S'); % find the index with string dimension + if isempty(Sdim), Sdim=-1, end; % mark as -1 if not existing + +%% Define metadata variables and their attributes +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varId(ii),true,true,Compression); + for jj=1:length(f) + if ~isempty(strfind(f{jj},[var '_'])) + netcdf.putAtt(ncid,varId(ii),f{jj}(strfind(f{jj},[var '_'])+length([var '_']):end),Obj.(f{jj})); + end + end + end + end + +%% Define data variables and their attributes +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varIdD(ii),true,true,Compression); + for jj=1:length(fod) + if ~isempty(strfind(fod{jj},[var '_'])) + netcdf.putAtt(ncid,varIdD(ii),fod{jj}(strfind(fod{jj},[var '_'])+length([var '_']):end),Obj.Data.(fod{jj})); + end + end + end + end + +%% End of definition + netcdf.endDef(ncid); + +%% Save metadata variables +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if length(ids)>1 + if iscell(Obj.(var)) + c=char(permute(Obj.(var),length(ids):-1:1)); + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % array 'ext' causes warnings in Octave in next row; 'strings' command would work better than 'zeros' but it is not supported in Octave + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),permute(Obj.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.(var)) + c=char(Obj.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),Obj.(var)); + end + end + end + end + +%% Save data variables +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if length(ids)>1 + if iscell(Obj.Data.(var)) + c=char(permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % array 'ext' causes warnings in Octave in next row; 'strings' command would work better than 'zeros' but it is not supported in Octave + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.Data.(var)) + c=char(Obj.Data.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),Obj.Data.(var)); + end + end + end + end + +catch ME +% if ~strcmp(ME.identifier,'MATLAB:imagesci:netcdf:libraryFailure') + netcdf.close(ncid); +% end + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message]); + +end +netcdf.close(ncid); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef64976aa6f50cc86d9e0705ccb4500a115980bf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/readme.txt @@ -0,0 +1,18 @@ +This is a readme file for the SOFA Toolbox for Matlab and Octave. + +* Add the "SOFAtoolbox" directory to Matlab search path: Use "Add Folder" (don't use "Add with Subfolders"!) +* Start the Toolbox: execute "SOFAstart" in Matlab or Octave. +* No HRTF files to play around? Follow the advices in the readme.txt files in the HRTFs directories. +* Explore the Toolbox: execute some of the "demo_" files in the directory "demos". +* Learn more about SOFA: read the specs PDF in the directory "doc". +* Report a bug: send a ticket at https://github.com/sofacoustics/SOFAtoolbox/issues. +* Last changes? check the file "history.txt". + +Tested with Matlab R2018b (and higher) and Octave 4.2.1. + +Contact the main developers: Piotr Majdak <piotr.majdak@oeaw.ac.at> and Michael Mihocic <michael.mihocic@oeaw.ac.at> + +Many thanks go to Hagen Wierstorf <hagen.wierstorf@tu-berlin.de> for the Octave support. + +Acoustics Research Insitute (ARI) +Austrian Academy of Sciences (OeAW) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m new file mode 100644 index 0000000000000000000000000000000000000000..e31f2629726e419662b6c927c38d3155c07122fa --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m @@ -0,0 +1,326 @@ +% SOFA Toolbox - test script +% Test some of the SOFA Toolbox functionality + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: missing demos added, bugs fixed (09-10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +clc; close all; % clean-up first +tic; % timer +SOFAstart; +warning('off','SOFA:upgrade'); +warning('off','SOFA:load'); +warning('off','SOFA:save'); + +%% Test converters TO SOFA +disp(' '); +disp('############################################'); +disp('####### TEST CONVERTERS TO SOFA ########'); +disp('############################################'); + +disp(' '); +disp('!!! Make sure that all source files are available in the HRTFs directories. See individual readme.txt files for more information !!!'); +disp(' '); + +%% demo_ARI2SOFA +disp('************** demo_ARI2SOFA **************'); +clear; +% subjectID='NH4'; % default +demo_ARI2SOFA +subjectID='NH2'; +demo_ARI2SOFA +disp('*** Finished: demo_ARI2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_BTDEI2SOFA +disp('************** demo_BTDEI2SOFA **************'); +clear; +demo_BTDEI2SOFA; +disp('*** Finished: demo_BTDEI2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_CIPIC2SOFA +disp('************** demo_CIPIC2SOFA **************'); +clear; +try + demo_CIPIC2SOFA; + disp('*** Finished: demo_CIPIC2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_CIPIC2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\data\CIPIC\ directory.') +end +disp(' '); + +%% demo_FHK2SOFA +clear; +% if ~exist('OCTAVE_VERSION','builtin') +disp('************** demo_FHK2SOFA **************'); +demo_FHK2SOFA; +disp('*** Finished: demo_FHK2SOFA (Output: SOFA-file(s))'); disp(' '); +% else +% disp('Skipped: demo_CIPIC2SOFA'); disp(' '); +% end + +%% demo_LISTEN2SOFA +disp('************** demo_LISTEN2SOFA **************'); +clear; +subjectID='1002'; +try + demo_LISTEN2SOFA; + disp('*** Finished: demo_LISTEN2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_LISTEN2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\data\LISTEN\ directory.') +end +disp(' '); + +%% demo_MIT2SOFA +disp('************** demo_MIT2SOFA **************'); +clear; +% pinna='normal'; % default value +demo_MIT2SOFA; +pinna='large'; +demo_MIT2SOFA; +disp('*** Finished: demo_MIT2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_SCUT2SOFA +disp('************** demo_SCUT2SOFA **************'); +clear; +try + demo_SCUT2SOFA; + disp('*** Finished: demo_SCUT2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_SCUT2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\data\SCUT\ directory.') +end +disp(' '); + +%% demo_TUBerlin2SOFA +disp('************** demo_TUBerlin2SOFA **************'); +clear; +radius=[0.5 1 2 3]; +demo_TUBerlin2SOFA; +disp('*** Finished: demo_TUBerlin2SOFA (Output: SOFA-file(s))'); disp(' '); + + +%% Test converters FROM SOFA +disp('############################################'); +disp('###### TEST CONVERTERS FROM SOFA #######'); +disp('############################################'); + +%% demo_SOFA2ARI +disp('************** demo_SOFA2ARI **************'); +clear; +demo_SOFA2ARI; +% SOFAplotGeometry(Obj); +disp('*** Finished: demo_SOFA2ARI'); disp(' '); + +%% demo_SOFAHRTF2DTF +disp('************** demo_SOFAHRTF2DTF **************'); +clear; +demo_SOFAHRTF2DTF; +disp('*** Finished: demo_SOFAHRTF2DTF (Output: Figure(s))'); disp(' '); + + +%% Test SOFA functions +disp('############################################'); +disp('###### TEST SOFA FUNCTIONS #######'); +disp('############################################'); + +%% demo_SOFAload +% Test SOFAload +disp('************** demo_SOFAload **************'); +clear; +demo_SOFAload; +disp('*** Finished: demo_SOFAload'); disp(' '); + +%% demo_SOFAmerge +% Test SOFAmerge and create TU-Berlin KEMAR file with multiple radii +disp('************** demo_SOFAmerge **************'); +clear; +demo_SOFAmerge; +disp('*** Finished: demo_SOFAmerge (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_SOFAplotGeometry +disp('************** demo_SOFAplotGeometry **************'); +clear; +demo_SOFAplotGeometry; +disp('*** Finished: demo_SOFAplotGeometry (Output: Figure(s))'); disp(' '); + +%% demo_SOFAplotHRTF +% Test plotting HRTFs +disp('************** demo_SOFAplotHRTF **************'); +demo_SOFAplotHRTF +disp('*** Finished: demo_SOFAplotHRTF (Output: Figure(s))'); disp(' '); + +% %% demo_plot_trumpet_directivity +% % Test plotting HRTFs +% disp('************** demo_plot_trumpet_directivity **************'); +% demo_plot_trumpet_directivity +% disp('*** Finished: demo_plot_trumpet_directivity (Output: Figure(s))'); disp(' '); + +%% demo_SOFAsave +disp('************** SOFAsave **************'); +clear; +demo_SOFAsave; +disp('*** Finished: SOFAsave (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAspat +% Test SOFAspat, but do not play +disp('************** demo_SOFAspat **************'); +clear; +dontplay=1; +demo_SOFAspat; +disp('*** Finished: demo_SOFAspat (Output: Figure(s))'); disp(' '); + +%% demo_SOFAstrings +% Test using string arrays +disp('************** demo_SOFAstrings **************'); +demo_SOFAstrings +disp('*** Finished: demo_SOFAstrings (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAvariables +% Test variables handling +disp('************** demo_SOFAvariables **************'); +demo_SOFAvariables +disp('*** Finished: demo_SOFAvariables (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAexpandcompact +% Test SOFAexpand and SOFAcompact +disp('************** demo_SOFAexpandcompact **************'); +clear; +demo_SOFAexpandcompact; +disp('*** Finished: demo_SOFAexpandcompact'); disp(' '); + +%% demo_SOFAcalculateITD +disp('************** demo_SOFAcalculateITD **************'); +clear; +demo_SOFAcalculateITD; +disp('*** Finished: demo_SOFAcalculateITD (Output: Figure(s))'); disp(' '); + +%% demo_SOFAcalculateLFE +disp('************** demo_SOFAcalculateLFE **************'); +clear; +demo_SOFAcalculateLFE; +disp('*** Finished: demo_SOFAcalculateLFE (Output: Figure(s))'); disp(' '); + + +%% Test SOFA conventions +disp('############################################'); +disp('###### TEST SOFA CONVENTIONS #######'); +disp('############################################'); + +%% demo_FreeFieldDirectivityTF +disp('************** demo_FreeFieldDirectivityTF **************'); +clear; +demo_FreeFieldDirectivityTF; +disp('*** Finished: demo_FreeFieldDirectivityTF (Output: Figure(s))'); disp(' '); + +%% demo_FreeFieldHRIR +disp('************** demo_FreeFieldHRIR **************'); +clear +demo_FreeFieldHRIR; +disp('*** Finished: demo_FreeFieldHRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_FreeFieldHRTF +disp('************** demo_FreeFieldHRTF **************'); +clear; +demo_FreeFieldHRTF; +disp('*** Finished: demo_FreeFieldHRTF (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_General +disp('************** demo_General **************'); +clear +demo_General; +disp('*** Finished: General (Output: SOFA-file(s))'); disp(' '); + +%% demo_GeneralFIR +disp('************** demo_GeneralFIR **************'); +clear +demo_GeneralFIR; +disp('*** Finished: demo_GeneralFIR (Output: SOFA-file(s))'); disp(' '); + +%% GeneralFIRE: outdated, use GeneralFIR-E instead + +%% demo_GeneralFIR-E +% replacing GeneralFIR +disp('************** demo_GeneralFIR_E **************'); +clear +demo_GeneralFIR_E; +disp('*** Finished: GeneralFIR_E (Output: SOFA-file(s))'); disp(' '); + +%% GeneralString: used in demo_SOFAstrings + +%% demo_GeneralTF +disp('************** demo_GeneralTF **************'); +clear +demo_GeneralTF; +disp('*** Finished: GeneralTF (Output: SOFA-file(s))'); disp(' '); + +%% demo_GeneralTF-E +disp('************** demo_GeneralTF_E **************'); +clear +demo_GeneralTF_E; +disp('*** Finished: GeneralTF-E (Output: SOFA-file(s))'); disp(' '); + +%% demo_MultiSpeakerBRIR +disp('************** demo_MultiSpeakerBRIR **************'); +clear +demo_MultiSpeakerBRIR; +disp('*** Finished: MultiSpeakerBRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleFreeFieldHRIR2TF +% Test conversions from SimpleFreeFieldHRIR to SimpleFreeFieldHRTF +disp('************** demo_SimpleFreeFieldHRIR2TF **************'); +clear; +demo_SimpleFreeFieldHRIR2TF; +disp('*** Finished: demo_SimpleFreeFieldHRIR2TF (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleFreeFieldHRSOS +disp('************** demo_SimpleFreeFieldHRSOS **************'); +clear +demo_SimpleFreeFieldHRSOS; +disp('*** Finished: SimpleFreeFieldHRSOS (Output: SOFA-file(s))'); disp(' '); + +%% SimpleFreeFieldHRTF +% used in function demo_SimpleFreeFieldHRIR2TF + +%% demo_SimpleFreeFieldSOS +disp('************** SimpleFreeFieldSOS **************'); +clear +demo_SimpleFreeFieldSOS; +disp('*** Finished: SimpleFreeFieldSOS (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleHeadphoneIR +% old name: demo_HpIR +disp('************** demo_SimpleHeadphoneIR **************'); +clear; +demo_SimpleHeadphoneIR; +disp('*** Finished: demo_SimpleHeadphoneIR (Output: Figure(s))'); disp(' '); + +%% demo_SingleRoomDRIROlcldenburg +% Test SingleRoomDRIR +disp('************** demo_SingleRoomDRIROldenburg **************'); +clear +demo_SingleRoomDRIROldenburg; +disp('*** Finished: demo_SingleRoomDRIROldenburg (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_SingleRoomMIMOSRIR +disp('************** demo_SingleRoomMIMOSRIR **************'); +clear +demo_SingleRoomMIMOSRIR; +disp('*** Finished: demo_SingleRoomMIMOSRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_SingleRoomSRIR +disp('************** SingleRoomSRIR **************'); +clear +demo_SingleRoomSRIR; +disp('*** Finished: SingleRoomSRIR (Output: SOFA-file(s))'); disp(' '); + +%% Epilogue +disp('##############################################'); +disp('#### COMPLETED ALL DEMOS SUCCESSFULLY ####'); +disp('##############################################'); +toc; % timer diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/ARI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/ARI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..c0aaf14e32a9d4ceb1688ae739a6c25805c7e813 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/ARI/readme.txt @@ -0,0 +1,7 @@ +Save here the data from the ARI database, http://www.oeaw.ac.at/isf/hrtf +Direct link to ARI database: https://projects.ari.oeaw.ac.at/research/experimental_audiology/hrtf/database/hrtfItEARI.html + +The data must be in the format as downloaded from ARI, that is NHX\hrtf_M_dtf 256.mat where NHX is the ARI subject ID. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/BTDEI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/BTDEI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba118e57056213ea47599e974a08bb1c3d1fc175 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/BTDEI/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the BT-DEI database, http://padva.dei.unipd.it/?page_id=345 +The data must be in the format as downloaded from BT-DEI, that is HXXX\SYYY\... where XXX is the headphone type and YYY the subject ID (three digits each). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/CIPIC/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/CIPIC/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..4c044289f4613a88d3e3f91a97481bda9b96ec8c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/CIPIC/readme.txt @@ -0,0 +1,7 @@ +Save here the data from the CIPIC database. +https://www.ece.ucdavis.edu/ + +The data must be in the format as downloaded from CIPIC, that is subject_XXX\hrir_final.mat where XXX is the CIPIC subject ID (three digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/FHK/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/FHK/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..1be7fba29b114ff59a967d5571c4b72d36ffaded --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/FHK/readme.txt @@ -0,0 +1,5 @@ +Save here the HRTF data from the FHK database, http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +The data must be in the format as downloaded from the server, i.e., HRIR_*.mat + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/IEM/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/IEM/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..c510933e895aba3d7880995bdf81b3a0f9299f7d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/IEM/readme.txt @@ -0,0 +1,4 @@ +Save here the 'LigetiHall_CubeletToSt450' data from the IEM database: https://phaidra.kug.ac.at/view/o:104376 + +SOFA API for Matlab and Octave +Michael Mihocic, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/LISTEN/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/LISTEN/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..83cc0f5ad0b95a934dd44d63904e440c278edbeb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/LISTEN/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the LISTEN database, http://recherche.ircam.fr/equipes/salles/listen/download.html +The data must be in the format as downloaded from IRCAM, that is IRC_XXXX\COMPENSATED\MAT\HRIR\IRC_XXX_C_HRIR.mat where XXXX is the LISTEN subject ID (4 digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/MIT KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/MIT KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..feb4a69d479a4ef84b7fea7bc5042533c31ec204 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/MIT KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the MIT database, http://sound.media.mit.edu/resources/KEMAR/full.zip +The data must be the "full" data as downloaded from MIT, that is full\elevE\PEeAa.wav where A and E is the azimuth and the elevation angles, respectively, and P is the pinna used, that is, L (normal pinna) or (large pinna). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/Oldenburg/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/Oldenburg/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..85709e35dfc0354dae14e3a203fcc41f607c73a2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/Oldenburg/readme.txt @@ -0,0 +1,6 @@ +Save here the data from the Oldeburg database, http://sirius.physik.uni-oldenburg.de/downloads/hrir/HRIR_database_mat.zip + +Note: before downloading that using that data, you must go to http://medi.uni-oldenburg.de/hrir/html/download.html and accept the form. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SCUT/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SCUT/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..a1cfbef2581b7503002efd3e57ac41d986efefc7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SCUT/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the SCUT database (Bosun Xie, Ghongzhou, China) +The data must be in the format as provided by the SCUT, e.g., the nearfield KEMAR data in the directory "nearfield". + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..7270aa38aa0f9978e68abd057e0c8fcae913d5d4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/readme.txt @@ -0,0 +1,7 @@ +SOFA files go here. + +When used with the default settings of SOFAdbURL and SOFAdbPath, this directory reflects http://www.sofacoustics.org/data/ + + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/sofatoolbox_test/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/sofatoolbox_test/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..458ab5cc8fb3332208879a114c34cc4a7754e885 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/sofatoolbox_test/readme.txt @@ -0,0 +1,8 @@ +SOFA files go here. They can be + +* manually downloaded by you from http://tinyurl.com/sofaHRTFs +* automatically created by the Toolbox by demo_ functions when the source HRTFs are available +* automatically downloaded by the Toolbox from http://www.sofacoustics.org/data/sofatoolbox_test when requested and available + +SOFA Toolbox for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/TU-Berlin KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/TU-Berlin KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..f80db755519a8b4da271e7c23edef97010027dcd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/data/TU-Berlin KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the TU-Berlin database, https://doi.org/10.5281/zenodo.4459911 +The data must be in the format as downloaded from TU Berlin. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO 1.0.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO 1.0.fodt new file mode 100644 index 0000000000000000000000000000000000000000..8501cc62e07c124f2ea3aed23324efd71d20015c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO 1.0.fodt @@ -0,0 +1,1280 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 1.0</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>247</meta:editing-cycles><meta:editing-duration>P2DT12H58S</meta:editing-duration><meta:generator>LibreOffice/6.2.4.2$Windows_X86_64 LibreOffice_project/2412653d852ce75f65fbfa83fb7e7b669a126d64</meta:generator><dc:date>2019-07-30T11:18:40.946000000</dc:date><dc:creator>Piotr Majdak</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="35" meta:word-count="431" meta:character-count="2885" meta:non-whitespace-character-count="2506"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">28737</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">17969</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">13183</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">1820</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">28736</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">17967</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">13923478</config:config-item> + <config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Mangal1" svg:font-family="Mangal"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Zeichenformat" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial1"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial1"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00d41fec" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T19" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T20" style:family="text"> + <style:text-properties officeooo:rsid="00d41fec"/> + </style:style> + <style:style style:name="T21" style:family="text"> + <style:text-properties officeooo:rsid="00d47496"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L3"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">Matlab/Octave API for SOFA </text:span><text:title>version 1.0</text:title><text:tab/><text:span text:style-name="T2"><text:tab/>Page: </text:span><text:span text:style-name="T2"><text:page-number text:select-page="current">1</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P29">Matlab/Octave API for SOFA</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T10">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T6">Acoustics Research Institute </text:span><text:span text:style-name="T9">(ARI)</text:span><text:span text:style-name="T6">, <text:line-break/>Austrian Academy of Sciences </text:span><text:span text:style-name="T9">(OeAW)</text:span><text:span text:style-name="T6"><text:line-break/></text:span><text:span text:style-name="T7">Vienna</text:span><text:span text:style-name="T6">, Austria</text:span><text:span text:style-name="T10"><text:line-break/></text:span><text:span text:style-name="T8"><</text:span><text:span text:style-name="T5">piotr@majdak.com</text:span><text:span text:style-name="T8">></text:span></text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T16">This document contains preliminary remarks on the <text:line-break/>API_MO </text:span><text:span text:style-name="T16"><text:title>version 1.0</text:title></text:span><text:span text:style-name="T16">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T17">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list2795606257" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P30"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P40"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T10">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P30"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T15">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T15">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P31"><text:span text:style-name="Strong_20_Emphasis">Wolfgang Hrauda </text:span><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T5">wolfgang.hrauda@gmx.at</text:span></text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P32" text:outline-level="2"/> + <text:h text:style-name="P7" text:outline-level="1">STARTING the API</text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T19">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the API.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt <text:span text:style-name="T20">or help SOFAstart.</text:span></text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the API are provided. This is the first place to get familiar with the structure of the API.</text:p> + <text:p text:style-name="P23">Note that for the demonstration of conversion functions, you will most probably need to download some non-SOFA HRTF files first. See readme.txt files in the HRTF directories of the corresponding non-SOFA format.</text:p> + <text:h text:style-name="P6" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P16">All the SOFA information is stored in the a variable which we call SOFA object here. <text:span text:style-name="T20">Such an object is, for example, returned by the function SOFAload. </text:span>In that object:</text:p> + <text:list xml:id="list1306107549" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P33">“GLOBAL_” <text:span text:style-name="T20">are all g</text:span>lobal attributes. <text:span text:style-name="T21">Use prefix GLOBAL_ to add your global attributes.</text:span> </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P36">Variables are stored with their names as they are.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="T20">An a</text:span>ttribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P34">“Data.” <text:span text:style-name="T20">is a </text:span>separate structure <text:span text:style-name="T20">containing </text:span>the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33">“PRIVATE” <text:span text:style-name="T20">is a</text:span> structure with private data for application use. <text:span text:style-name="T20">Here you can store your private variables which belong to the SOFA object. P</text:span>rivate <text:span text:style-name="T20">variables</text:span> won't be saved when saving <text:span text:style-name="T20">the</text:span> object <text:span text:style-name="T20">as a SOFA file.</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35">“API” <text:span text:style-name="T20">contains </text:span>internal variables <text:span text:style-name="T20">of the API. Do not modify them, use SOFAupdateDimensions() to update them according to your data. These variables</text:span> are <text:span text:style-name="T21">useful for handling the SOFA data</text:span>:</text:p> + <text:list> + <text:list-item> + <text:p text:style-name="P35">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">Use SOFAaddVariable() to add a new variable. </text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P17">Further resources can be found:</text:p> + <text:list xml:id="list2018448349" text:style-name="L3"> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T20">API_MO</text:span>/readme.txt provides a short description of the API.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T20">API_MO</text:span>/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">doc/specs provides specifications of the currently supported SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/SOFA stores SOFA files. Per default, it mirrors http://sofacoustics.org/data.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/SOFA/sofa_api_mo_test: here, the automatically created SOFA files will be saved for testing purposes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/other directories: directories containing HRTF files stored in other formats than SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">http://sofaconventions.org provides the most recent information on SOFA.</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt new file mode 100644 index 0000000000000000000000000000000000000000..63ebe4d9a21843cd82c9280b34b99372606617a0 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt @@ -0,0 +1,1248 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 0.4</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>234</meta:editing-cycles><meta:editing-duration>P2DT11H41M48S</meta:editing-duration><meta:generator>LibreOffice/4.2.1.1$Windows_x86 LibreOffice_project/d7dbbd7842e6a58b0f521599204e827654e1fb8b</meta:generator><dc:date>2014-03-20T17:53:51.716000000</dc:date><dc:creator>Piotr Majdak</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="28" meta:word-count="272" meta:character-count="1831" meta:non-whitespace-character-count="1599"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="int">34555</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="int">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="int">26169</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="int">21063</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="int">15688</config:config-item> + <config:config-item config:name="ViewTop" config:type="int">37447</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="int">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="int">34555</config:config-item> + <config:config-item config:name="VisibleRight" config:type="int">26167</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="int">55615</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">13612822</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Mangal1" svg:font-family="Mangal"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L4"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:list-style-name="L1"/> + <style:style style:name="P26" style:family="paragraph" style:list-style-name="L2"/> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L3"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L4"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:layout-grid-snap-to-characters="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:layout-grid-snap-to-characters="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">Matlab and Octave API for SOFA </text:span><text:title>version 0.4</text:title><text:tab/><text:span text:style-name="T2"><text:tab/>Page: </text:span><text:span text:style-name="T2"><text:page-number text:select-page="current">2</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P29">Matlab and Octave API for SOFA</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T9">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T6">Acoustics Research Institute, Austrian Academy of Sciences, </text:span><text:span text:style-name="T7">Vienna</text:span><text:span text:style-name="T6">, Austria</text:span><text:span text:style-name="T9"><text:line-break/></text:span><text:span text:style-name="T8"><</text:span><text:span text:style-name="T5">piotr@majdak.com</text:span><text:span text:style-name="T8">></text:span></text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T15">This document contains preliminary remarks on the <text:line-break/>API_MO </text:span><text:span text:style-name="T15"><text:title>version 0.4</text:title></text:span><text:span text:style-name="T15">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T16">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list6831239085214927904" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P17"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P24"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T9">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P17"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T14">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T14">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P18" text:outline-level="2"/> + <text:h text:style-name="P28" text:outline-level="1">STARTING the API</text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T18">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the API.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt.</text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the API are provided. This is the first place to get familiar with the structure of the API.</text:p> + <text:h text:style-name="P27" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P23">All the SOFA information is stored in the a variable which we call SOFA object here. In that object:</text:p> + <text:list xml:id="list382891697804604485" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P19">“Data.”: separate structure with the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">“GLOBAL_”: Global attributes </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">Attribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">“PRIVATE”: structure with private data for application use. Private data won't be saved when saving a SOFA object. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">API internal variables are:</text:p> + </text:list-item> + </text:list> + <text:list xml:id="list7731056547229950280" text:style-name="L4"> + <text:list-item> + <text:p text:style-name="P22">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P22">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P20">Further resources can be found:</text:p> + <text:list xml:id="list1373325075875023343" text:style-name="L3"> + <text:list-item> + <text:p text:style-name="P21">api_mo/readme.txt provides a short description of the API.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">api_mo/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">doc/specs provides specifications of the currently supported SOFA</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">http://sofaconventions.org provides the most recent information on SOFA</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/Conventions2Wiki.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/Conventions2Wiki.m new file mode 100644 index 0000000000000000000000000000000000000000..36d1c1bed5a615c7c4e83b2cdb8387705d34dced --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/Conventions2Wiki.m @@ -0,0 +1,36 @@ +%% Convert all convention files to Wiki tables + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated, license text added (28.10.2021) + +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +p=fullfile('..','SOFAtoolbox','conventions'); +d=dir([p filesep '*.csv']); +conventions={}; +for ii=1:length(d) + dn=d(ii).name; + conventions{ii}=dn(1:end-4); +end + +for jj=1:length(conventions) + fid=fopen([p filesep conventions{jj} '.csv']); + C=textscan(fid,'%s%s%s%s%s%s','Delimiter','\t','Headerlines',1); + fclose(fid); + fid=fopen([conventions{jj} '.txt'],'w'); + fprintf(fid,'{| border="1"\n!Name\n!Default\n![[SOFA_conventions#AnchorFlags|Flags]]\n![[SOFA_conventions#AnchorDimensions|Dimensions]]\n!Type\n!Comment\n'); +% C2=regexprep(C{2},'''', '’'); % replace single quota (') by ′ + for ii=1:length(C{1}) + fprintf(fid,['|-\n|' C{1}{ii} '||<nowiki>' C{2}{ii} '</nowiki>||' C{3}{ii} '||' C{4}{ii} '||' C{5}{ii} '||' C{6}{ii} '\n']); + end + fprintf(fid,'|}'); + fclose(fid); +end +disp (' ** done **'); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/Toolbox 2.0.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/Toolbox 2.0.fodt new file mode 100644 index 0000000000000000000000000000000000000000..4afadfdb8e9f077972c747328dad97521cb85dd1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/doc/Toolbox 2.0.fodt @@ -0,0 +1,1277 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:officeooo="http://openoffice.org/2009/office" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 2.0</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>250</meta:editing-cycles><meta:editing-duration>P2DT12H5M37S</meta:editing-duration><meta:generator>LibreOffice/7.3.4.2$Windows_X86_64 LibreOffice_project/728fec16bd5f605073805c3c9e7c4212a0120dc5</meta:generator><dc:date>2022-07-28T13:12:29.231000000</dc:date><dc:creator>Michael Mihocic</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="36" meta:word-count="436" meta:character-count="2961" meta:non-whitespace-character-count="2578"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">38022</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">18840</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">21701</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">9500</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">38021</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">18838</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">14009041</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item> + <config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item> + <config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item> + <config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal"/> + <style:font-face style:name="Mangal1" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"> + <style:tab-stops> + <style:tab-stop style:position="8.5cm" style:type="center"/> + <style:tab-stop style:position="17cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Index_20_Heading" style:display-name="Index Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" loext:opacity="100%" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Zeichenformat" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" loext:num-list-format="%1%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" loext:num-list-format="%1%.%2%." style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" loext:num-list-format="%1%.%2%.%3%." style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" loext:num-list-format="%1%.%2%.%3%.%4%." style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" loext:num-list-format="%1%.%2%.%3%.%4%.%5%." style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" loext:num-list-format="%2%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" loext:num-list-format="%3%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" loext:num-list-format="%5%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" loext:num-list-format="%6%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" loext:num-list-format="%8%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" loext:num-list-format="%9%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" loext:num-list-format="%1%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" loext:num-list-format="%2%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" loext:num-list-format="%3%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" loext:num-list-format="%4%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" loext:num-list-format="%5%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" loext:num-list-format="%6%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" loext:num-list-format="%7%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" loext:num-list-format="%8%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" loext:num-list-format="%9%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" loext:num-list-format="%10%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" loext:num-list-format="%1%." style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" loext:num-list-format="%2%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" loext:num-list-format="%3%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" loext:num-list-format="%4%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" loext:num-list-format="%5%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" loext:num-list-format="%6%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" loext:num-list-format="%7%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" loext:num-list-format="%8%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" loext:num-list-format="%9%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" loext:num-list-format="%1%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" loext:num-list-format="%1%.%2%." style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" loext:num-list-format="%1%.%2%.%3%." style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" loext:num-list-format="%1%.%2%.%3%.%4%." style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" loext:num-list-format="%1%.%2%.%3%.%4%.%5%." style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" loext:num-list-format="%6%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" loext:num-list-format="%7%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" loext:num-list-format="%8%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" loext:num-list-format="%9%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" loext:num-list-format="%1%." style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" loext:num-list-format="%2%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" loext:num-list-format="%3%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" loext:num-list-format="%4%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" loext:num-list-format="%5%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" loext:num-list-format="%6%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" loext:num-list-format="%7%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" loext:num-list-format="%8%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" loext:num-list-format="%9%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" loext:num-list-format="[%1%]" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" loext:num-list-format="%2%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" loext:num-list-format="%3%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" loext:num-list-format="%4%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" loext:num-list-format="%5%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" loext:num-list-format="%6%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" loext:num-list-format="%7%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" loext:num-list-format="%8%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" loext:num-list-format="%9%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Subtitle"> + <style:paragraph-properties style:writing-mode="lr-tb"/> + <style:text-properties officeooo:rsid="00d5c2d1" officeooo:paragraph-rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Subtitle"> + <style:paragraph-properties style:writing-mode="lr-tb"/> + </style:style> + <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P41" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P42" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P43" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P44" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto" style:writing-mode="lr-tb"/> + <style:text-properties officeooo:rsid="00cbc3ea" officeooo:paragraph-rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00d41fec" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T19" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T20" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T21" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T22" style:family="text"> + <style:text-properties officeooo:rsid="00d41fec"/> + </style:style> + <style:style style:name="T23" style:family="text"> + <style:text-properties officeooo:rsid="00d47496"/> + </style:style> + <style:style style:name="T24" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" loext:num-list-format="%2%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" loext:num-list-format="%3%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" loext:num-list-format="%5%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" loext:num-list-format="%6%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" loext:num-list-format="%8%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" loext:num-list-format="%9%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" loext:num-list-format="%2%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" loext:num-list-format="%3%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" loext:num-list-format="%5%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" loext:num-list-format="%6%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" loext:num-list-format="%8%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" loext:num-list-format="%9%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"> + <style:drawing-page-properties draw:background-size="full"/> + </style:style> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">SOFA Toolbox for Matlab/Octave</text:span><text:span text:style-name="T2"> </text:span><text:title>version 2.0</text:title><text:tab/><text:span text:style-name="T3"><text:tab/>Page: </text:span><text:span text:style-name="T3"><text:page-number text:select-page="current">2</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" draw:style-name="dp1" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3" draw:style-name="dp1"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4" draw:style-name="dp1"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4" draw:style-name="dp1"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P44">SOFA <text:span text:style-name="T24">Toolbox for </text:span>Matlab/Octave</text:p> + <text:p text:style-name="P31">(previously SOFA API_MO)</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T12">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T8">Acoustics Research Institute </text:span><text:span text:style-name="T11">(ARI)</text:span><text:span text:style-name="T8">, <text:line-break/>Austrian Academy of Sciences </text:span><text:span text:style-name="T11">(OeAW)</text:span><text:span text:style-name="T8"><text:line-break/></text:span><text:span text:style-name="T9">Vienna</text:span><text:span text:style-name="T8">, Austria</text:span><text:span text:style-name="T12"><text:line-break/></text:span><text:span text:style-name="T10"><</text:span><text:span text:style-name="T7">piotr@majdak.com</text:span><text:span text:style-name="T10">></text:span></text:p> + <text:p text:style-name="P32"><text:span text:style-name="T18">This document contains preliminary remarks on the <text:line-break/></text:span><text:span text:style-name="T24">SOFA Toolbox</text:span><text:span text:style-name="T18"> </text:span><text:span text:style-name="T18"><text:title>version 2.0</text:title></text:span><text:span text:style-name="T18">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T19">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list301348430" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P34"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T12">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T17">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T17">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35"><text:span text:style-name="Strong_20_Emphasis">Wolfgang Hrauda </text:span><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T7">wolfgang.hrauda@gmx.at</text:span></text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P36" text:outline-level="2"/> + <text:h text:style-name="P11" text:outline-level="1">STARTING the <text:span text:style-name="T24">Toolbox</text:span></text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T21">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the <text:span text:style-name="T24">Toolbox</text:span>.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt <text:span text:style-name="T22">or help SOFAstart.</text:span></text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the Toolbox are provided. This is the first place to get familiar with the structure of the Toolbox.</text:p> + <text:p text:style-name="P24">Note that for the demonstration of conversion functions, you will most probably need to download some non-SOFA HRTF files first. See readme.txt files in the HRTF directories of the corresponding non-SOFA format.</text:p> + <text:h text:style-name="P9" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P10">All the SOFA information is stored in the a variable which we call SOFA object here. <text:span text:style-name="T22">Such an object is, for example, returned by the function SOFAload. </text:span>In that object:</text:p> + <text:list xml:id="list2273856870" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P37">“GLOBAL_” <text:span text:style-name="T22">are all g</text:span>lobal attributes. <text:span text:style-name="T23">Use prefix GLOBAL_ to add your global attributes.</text:span> </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P40">Variables are stored with their names as they are.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T22">An a</text:span>ttribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">“Data.” <text:span text:style-name="T22">is a </text:span>separate structure <text:span text:style-name="T22">containing </text:span>the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">“PRIVATE” <text:span text:style-name="T22">is a</text:span> structure with private data for application use. <text:span text:style-name="T22">Here you can store your private variables which belong to the SOFA object. P</text:span>rivate <text:span text:style-name="T22">variables</text:span> won't be saved when saving <text:span text:style-name="T22">the</text:span> object <text:span text:style-name="T22">as a SOFA file.</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">“API” <text:span text:style-name="T22">contains </text:span>internal variables <text:span text:style-name="T22">of the </text:span><text:span text:style-name="T24">Toolbox </text:span><text:span text:style-name="T22">API. Do not modify them, use SOFAupdateDimensions() to update them according to your data. These variables</text:span> are <text:span text:style-name="T23">useful for handling the SOFA data</text:span>:</text:p> + <text:list> + <text:list-item> + <text:p text:style-name="P39">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + </text:list-item> + <text:list-item> + <text:p text:style-name="P41">Use SOFAaddVariable() to add a new variable. </text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P18">Further resources can be found:</text:p> + <text:list xml:id="list3009974912" text:style-name="L2"> + <text:list-item> + <text:p text:style-name="P42">SOFAtoolbox/readme.txt provides a short description of the SOFAtoolbox.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">SOFAtoolbox/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">doc/specs provides specifications of the currently supported SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/SOFA stores SOFA files. Per default, it mirrors http://sofacoustics.org/data.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/SOFA/sofa<text:span text:style-name="T24">toolbox</text:span>_test: here, the automatically created SOFA files will be saved for testing purposes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/other directories: directories containing HRTF files stored in other formats than SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">http://sofaconventions.org provides the most recent information on SOFA.</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/license.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..355bc6cdd47000634dc919a2f65235c850219a88 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/deps/SOFA_API/SOFAtoolbox-master/license.txt @@ -0,0 +1,287 @@ +EUROPEAN UNION PUBLIC LICENCE v. 1.2 +EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + + Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +1. Definitions + +In this Licence, the following terms have the following meaning: + +- ‘The Licence’: this Licence. + +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. + +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. + +- ‘The Work’: the Original Work or its Derivative Works. + +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. + +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. + +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. + +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. + +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. + +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/release-notes.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/release-notes.md new file mode 100644 index 0000000000000000000000000000000000000000..4ad8c2420391ff97819998ebcd36f9a026f21d5e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/IoSR Toolbox/release-notes.md @@ -0,0 +1,77 @@ +# v2.8 - 17th June 2017 + +- Added kernelDensity function. +- boxPlot: Added ‘violin’ methods and properties for making violin plots. +- boxPlot: Added various violin-related options. Also modified the scatter offset to use kernel density rather than histogram. +- boxPlot: Added themeColor property, allowing the various colours for the theme to be changed via a single property. +- calcSnr: Prevent rank deficient warning when output is zeros. + +# v2.7 - 28th March 2017 + +- Added true functional boxplot. +- Added alternative perceptual centroid function. +- Added caching of various dependent properties to iosr.bss.mixture class. +- Added identifiers to all warnings and errors. +- Updated loudness weighting calculations for A and C to better match IEC 61672. Added normalisation ISO 226 curve at 1kHz to bring it in to line with other weighting functions. +- Improved extrapolation of ISO 226 function. Added params output to return reference values. +- Updated SOFA API version in installer. +- Bug fixes and documentation improvements. + +# v2.6 - 6th March 2017 + +Added a number of properties and methods to the iosr.bss.mixture class. Added whiskers property to iosr.statistics.functionalSpreadPlot. Other minor bug fixes and documentation improvements. + +# v2.5 - 20th February 2017 + +Generalised iosr.bss.mixture class to support arbitrary spatial configurations, as well as none. Added decomposition properties to allow direct calculation of ideal masks, and application of masks. Currently, only STFT is supported; will add gammatone in due course. Added a number of of measures related to the mask and to signal overlap. + +A few bug fixes. + +# v2.4.1 - 18th January 2017 + +Added optional first argument to boxPlot and functionalSpreadPlot to specify axes in which to plot. + +# v2.4 - 15th December 2016 + +Added functionalSpreadPlot for making functional box plots and related plots. Also added statsPlot class and moved some boxPlot methods to the class, as they are shared with functionalSpreadPlot. + +# v2.3.2 - 13th October 2016 + +* Added check for OCTAVE in irStats, and a basic check for a unique peak. +* Corrected mistake in boxPlot documentation (pulled from TGabor). +* Moved important bits of documentation into chXcorr.m (the only separately-documented portion of the code). + +# v2.3.1 - 25th July 2016 + +* Minor tweak to magnitude calculation in matchEQ. +* Redefined TIR in mixture class as target w.r.t. sum of interfering sources. Updated documentation. + +# v2.3 - 19th July 2016 + +* Corrected code to restore current directory when installation is complete. +* Added function to generate BSS mixtures by combining sources in various ways. +* Added property to iosr.bss.mixture to return interferer filenames as char array. Also corrected bug setting properties when interferer comprises multiple sources. + +# v2.2.3 - 12th July 2016 + +Corrected boxPlot bug whereby x-separator line would disappear when setting y-axis limits to inf. + +# v2.2.2 - 10th July 2016 + +Corrected calls to other toolbox functions. + +# v2.2.1 - 8th July 2016 + +Fixed erroneous default 'method' in boxPlot. + +# v2.2 - 7th July 2016 + +Added install function that downloads dependencies and sets path. Fixed bug in boxPlot where some set functions check the old value rather than the new value. + +# v2.1 - 22nd June 2016 + +Added match EQ function. + +# v2 - 6th June 2016 + +Restructured toolbox into a Matlab package in order to appropriately restrict namespace. Consolidated some file/function names into a consistent format. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/LSpositionsUnity.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/LSpositionsUnity.m new file mode 100644 index 0000000000000000000000000000000000000000..a4c0742b137a1709dae051aa534389cc6efd80a5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/LSpositionsUnity.m @@ -0,0 +1,54 @@ + +% Script file to convert polar co-ordinates to cartesian +% The loudspeaker positions in the Unity setup +% Paper "Perceived quality and spatial impression of room reverberation in +% VR reprodution from measured iamge and acoustics +% Luca et al, 2019 + +r = 1.6;% Distance, Bacause the radius of the collider in Unity is 0.5 +% so we need to multiply that by 2 + +% Azimuths for 0 degree elevation +azim_0 = [0:15:180, -165:15:-15]; + +% The loudspeakers are irregularly positioned +% Azimuths for 30, & -30 Elevations +azim_30 = [0 30 45 60 90 120 135 150 180 -150 -135 -120 -90 -60 -45 -30]; +azim_90 = zeros(1,2); % Azimuths for 90, & -90 Elevations +azim = [azim_0, azim_30,azim_30, azim_90]'; % Azimuths + +elev = [zeros(1,size(azim_0,2)), -30*ones(1,size(azim_30,2)),... + 30*ones(1,size(azim_30,2)), -90, 90]'; % Elevations + +% To convert the angles in degrees to radians +azim_rad = (pi/180)*azim; +elev_rad = (pi/180)*elev; + +LS_polar = [azim_rad elev_rad]; + +% To convert the polar coordinates to the cartesian as in Unity +% where the y-axis is up-down +mid = r*cos(elev_rad); +x = mid.*cos(azim_rad); +y = r * sin(elev_rad); +z = mid.*sin(azim_rad); + +LS_cart =[(1:58)' x y z]; + +%% The coordinate conversion for our experiments LS setup +% 64 loudspeakers with azimuths and elevations as follows +% It converts the polar co-ordinates to Cartesian for Unity application + +load('DTU_ls_dirs_deg.mat') +azim64 = ls_dirs_deg(:,1); elev64 = ls_dirs_deg(:,2); +azim64_rad = (pi/180)*azim64; elev64_rad = (pi/180)*elev64; + +LS_polar64 = [azim64_rad elev64_rad]; +rd = 2.4; % The radius is set to 2.4 +% where the y-axis is up-down +mid64 = rd*cos(elev64_rad); +x64 = mid64.*cos(azim64_rad); +y64 = rd * sin(elev64_rad); +z64 = mid64.*sin(azim64_rad); + +LS_cart64 =[(1:64)' x64 y64 z64]; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Main_Immersive_EDT_RT60.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Main_Immersive_EDT_RT60.m new file mode 100644 index 0000000000000000000000000000000000000000..b3acd1ef3823da3aa2dff557f048f173457e7407 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Main_Immersive_EDT_RT60.m @@ -0,0 +1,57 @@ +addpath 'RIRs' 'IoSR Toolbox' 'octave' + +%% + +% MR room +[LS2_sweep, fs2] = audioread("sounds/MR_MDBNet/RIR_MR_Unity_bf.wav"); + +% KT room +%[LS2_sweep, fs2] = audioread("sounds/KT_MDBNet/RIR_KT_Unity_bf.wav"); +%[LS2_sweep, fs2] = audioread("sounds/KT_MDBNet/RIR_KT_truncated.wav"); +%[LS2_sweep, fs2] = audioread("sounds/KT_MDBNet/RIR_KT_gun_Unity_ch1_v2.wav"); + +% UL room +%[LS2_sweep, fs2] = audioread("sounds/UL_MDBNet/RIR_UL_Unity_bf.wav"); + +% ST room +%[LS2_sweep, fs2] = audioread("sounds/ST_MDBNet/RIR_ST_Unity_bf.wav"); +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% MR room +[RT, DRR, C50, Cfs, EDT] = ... +iosr.acoustics.irStats("sounds/MR_MDBNet/RIR_MR_Unity_bf.wav",'graph', true, 'spec', 'full'); + +% KT room +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/KT_MDBNet/RIR_KT_Unity_bf.wav",'graph', true, 'spec', 'full'); +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/KT_MDBNet/RIR_KT_truncated.wav",'graph', true, 'spec', 'full'); + + +% UL room +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/UL_MDBNet/RIR_UL_Unity_bf.wav",'graph', true, 'spec', 'full'); + +% ST room +%[RT, DRR, C50, Cfs, EDT] = ... +%iosr.acoustics.irStats("sounds/ST_MDBNet/RIR_ST_Unity_bf.wav",'graph', true, 'spec', 'full'); + +% Calculating Mean Values +mean_EDT = mean(EDT(3:8)); +mean_RT = mean(RT(3:8)); + + +t2 = 0:1/fs2:((length(LS2_sweep)-1)/fs2); + +figure; + +plot(t2,LS2_sweep(:,1).'); xlabel("time [s]"); ylabel("Amplitude"); title("RIR from sweep"); + +% Display Mean Values +disp('Mean RT60:'); +disp(mean_RT); + +disp('Mean EDT:'); +disp(mean_EDT); +%.......................................................................... +%.......................................................................... diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master.zip b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master.zip new file mode 100644 index 0000000000000000000000000000000000000000..9a2be172cdc76a205fc40f2e9e79aa790c698546 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master.zip differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+acoustics/irStats.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+acoustics/irStats.m new file mode 100644 index 0000000000000000000000000000000000000000..e95edaf3d3d69a3664afe812b3fdf750ba1bd340 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+acoustics/irStats.m @@ -0,0 +1,342 @@ +function [rt,drr,cte,cfs,edt] = irStats(filename,varargin) +%IRSTATS Calculate RT, DRR, Cte, and EDT for impulse response file +% +% RT = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the reverberation time +% (to -60 dB) using a method based on ISO 3382-1:2009. The function uses +% reverse cumulative trapezoidal integration to estimate the decay curve, +% and a linear least-square fit to estimate the slope between 0 dB and +% -60 dB. Estimates are taken in octave bands and the overall figure is +% an average of the 500 Hz and 1 kHz bands. +% +% FILENAME should be the full path to an audio file or the name of an +% audio file on the Matlab search path. The file can be of any format +% supported by the AUDIOREAD function, and have any number of channels; +% estimates (and plots) will be returned for each channel. +% +% The function returns a 1xN vector of RTs, where N is the number of +% channels in the audio file. +% +% The function determines the direct sound as the peak of the squared +% impulse response. +% +% [RT,DRR] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% direct-to-reverberant-ratio DRR for the impulse; DRR is a 1xN vector. +% This is calculated in the following way: +% +% DRR = 10 * log10( X(T0-C:T0+C)^2 / X(T0+C+1:end)^2 ) +% +% where X is the approximated integral of the impulse, T0 is the time of +% the direct impulse, and C=2.5ms [1]. +% +% [RT,DRR,CTE] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% early-to-late index CTE for the impulse; CTE is a 1xN vector. +% This is calculated in the following way: +% +% CTE = 10 * log10( X(T0-C:T0+TE)^2 / X(T0+TE+1:end)^2 ) +% +% where TE is 50 ms. +% +% [RT,DRR,CTE,CFS] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% octave-band centre frequencies CFS used in the calculation of RT. +% +% [RT,DRR,CTE,CFS,EDT] = IOSR.ACOUSTICS.IRSTATS(FILENAME) returns the +% early decay time EDT, which is the same size as RT. The slope of the +% decay curve is determined from the fit between 0 and -10 dB. The decay +% time is calculated from the slope as the time required for a 60 dB +% decay. +% +% ... = IOSR.ACOUSTICS.IRSTATS(...,'PARAMETER',VALUE) allows numerous +% parameters to be specified. These parameters are: +% +% 'graph' : {false} | true +% Controls whether decay curves are plotted. Specifically, graphs +% are plotted of the impulse response, decay curves, and linear +% least-square fit for each octave band and channel of the audio +% file. If the EDT output is specified, the EDT fit will also be +% plotted. +% 'te' : {0.05} | scalar +% Specifies the early time limit (in seconds). +% 'spec' : {'mean'} | 'full' +% Determines the nature of RT and EDT outputs. With spec='mean' +% (default) the reported RT and EDT are the mean of the 500 Hz +% and 1 kHz bands. With spec='full', the function returns the +% RT and EDT as calculated for each octave band returned in +% CFS; RT and EDT have size [M N] where M=length(CFS). +% 'y_fit' : {[0 60]} | two-element vector +% Specifies the decibel range over which the decay curve should +% be evaluated. For example, 'y_fit' may be [-5 -25] or [-5 -35] +% corresponding to the RT20 and RT30 respectively. +% 'correction' : {0.0025} | scalar +% Specifies the correction parameter C (in seconds) given above +% for DRR and CTE calculations. Values of up to 10 ms have been +% suggested in the literature. +% +% Octave-band filters are calculated according to ANSI S1.1-1986 and IEC +% standards. Note that the OCTDSGN function recommends centre frequencies +% fc in the range fs/200 < fc < fs/5. +% +% The author would like to thank Feifei Xiong for his input on the +% correction parameter. +% +% References +% +% [1] Zahorik, P., 2002: 'Direct-to-reverberant energy ratio +% sensitivity', The Journal of the Acoustical Society of America, +% 112, 2110-2117. +% +% See also AUDIOREAD, OCTDSGN. + +% Copyright 2016 University of Surrey. + + %% validate inputs and set options + + % check dependency + if exist('octdsgn','file')~=2 + web('http://uk.mathworks.com/matlabcentral/fileexchange/69-octave','-new','-browser') + error('iosr:irStats:OctaveToolbox','Please download and install the OCTAVE toolbox from: http://uk.mathworks.com/matlabcentral/fileexchange/69-octave') + end + + % check file exists + assert(exist(filename,'file')==2, 'iosr:irStats:invalidFile', ['iosr.acoustics.irStats: ' filename ' does not exist']) + + % set defaults + options = struct(... + 'graph',false,... + 'te',0.05,... + 'spec','mean',... + 'y_fit',[0 -60],... + 'correction',0.0025); + + % read parameter/value inputs + if nargin>1 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:irStats:nameValuePair','IRSTATS needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:irStats:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % check options size and type + assert(isvector(options.y_fit) && numel(options.y_fit)==2, 'iosr:irStats:invalidYfit', '''y_fit'' must be a two-element vector.') + assert(isscalar(options.correction), 'iosr:irStats:invalidCorrection', '''correction'' must be a scalar.') + assert(isscalar(options.te), 'iosr:irStats:invalidTe', '''te'' must be a scalar.') + assert(ischar(options.spec), 'iosr:irStats:invalidSpec', '''spec'' must be a char array.') + assert(islogical(options.graph) && numel(options.graph)==1, 'iosr:irStats:invalidGraph', '''graph'' must be logical.') + + % check for reasonable values + assert(all(options.y_fit<=0), 'iosr:irStats:invalidYfit', '''y_fit'' values must be less than or equal to 0.') + assert(options.te>=0, 'iosr:irStats:invalidTe', '''te'' must be greater than or equal to 0.') + assert(options.correction>=0, 'iosr:irStats:invalidCorrection', '''correction'' must be greater than or equal to 0.') + + %% read in audio file + + % read in impulse + [x,fs] = audioread(filename); + assert(fs>=5000, 'iosr:irStats:invalidFs', 'Sampling frequency is too low. FS must be at least 5000 Hz.') + assert(sum(abs(x(:)))>0, 'iosr:irStats:silence', 'The signal appears to be silent.') + + % set te in samples + te = round(options.te*fs); + + % Check sanity of te + assert(te<length(x), 'iosr:irStats:invalidTe', 'The specified early time limit te is longer than the duration of the impulse!') + + % get number of channels + numchans = size(x,2); + + %% set up octave-band filters + + % octave-band center frequencies + cfs = [31.25 62.5 125 250 500 1000 2000 4000 8000 16000]; + + % octave-band filter order + N = 3; + + % limit centre frequencies so filter coefficients are stable + cfs = cfs(cfs>fs/200 & cfs<fs/5); + cfs = cfs(:); + + % calculate filter coefficients + a = zeros(length(cfs),(2*N)+1); + b = zeros(length(cfs),(2*N)+1); + for f = 1:length(cfs) + [b(f,:),a(f,:)] = octdsgn(cfs(f),fs,N); + end + + %% perform calculations + + % empty matrices to fill + z = zeros([length(cfs) size(x)]); + rt_temp = zeros([length(cfs) numchans]); + edt = zeros([length(cfs) numchans]); + t0 = zeros(1,numchans); + drr = zeros(1,numchans); + cte = zeros(1,numchans); + + correction = round(options.correction*fs); + + % filter and integrate + for n = 1:numchans + % find direct impulse + peak = find(x(:,n).^2==max(x(:,n).^2)); + if numel(peak)>1 + warning('iosr:irStats:multiplePeaks','More than one peak found. Choosing first peak. Are you sure this is an impulse response?') + end + t0(n) = peak(1); + % draw figure + if options.graph + scrsz = get(0,'ScreenSize'); + figpos = [((n-1)/numchans)*scrsz(3) scrsz(4) scrsz(3)/2 scrsz(4)]; + figure('Name',['Channel ' num2str(n)],'OuterPosition',figpos); + end + % evaluate impulse in each octave band + for f = 1:length(cfs) + y = filter(b(f,:),a(f,:),x(:,n)); % octave-band filter + temp = cumtrapz(y(end:-1:1).^2); % decay curve + z(f,:,n) = temp(end:-1:1); + [rt_temp(f,n),E_rt,fit_rt] = calc_decay(z(f,t0:end,n),options.y_fit,60,fs,cfs(f)); % estimate RT + [edt(f,n),E_edt,fit_edt] = calc_decay(z(f,t0:end,n),[0,-10],60,fs,cfs(f)); % estimate EDT + if options.graph % plot + % time axes for different vectors + ty = ((0:length(y)-1)-t0(n))./fs; + tE_rt = (0:length(E_rt)-1)./fs; + tE_edt = (0:length(E_edt)-1)./fs; + % plot + subplot(length(cfs),2,(2*f)-1) + plot(ty,y,'k') % octave-band impulse + if f==1 + title({'Impulse response'; ''; [num2str(cfs(f)) ' Hz octave band']}) + else + title([num2str(cfs(f)) ' Hz octave band']) + end + if f==length(cfs) + xlabel('Time [s]') + else + set(gca,'xticklabel',[]); + end + ylabel('Amplitude') + set(gca,'position',[1 1 1 1.05].*get(gca,'position'),'xlim',[min(ty) max(ty)]); + subplot(length(cfs),2,2*f) + % energy decay and linear least-square fit + if nargout==5 + % plot EDT fit if EDT wanted + plot(tE_rt,E_rt,'-k',tE_rt,fit_rt,'--r',tE_edt,fit_edt,':b') + else + plot(tE_rt,E_rt,'-k',tE_rt,fit_rt,'--r') + end + % title for top row + if f==1 + title({'Decay curve'; ''; [num2str(cfs(f)) ' Hz octave band']}) + else + title([num2str(cfs(f)) ' Hz octave band']) + end + % x label for bottom row + if f==length(cfs) + xlabel('Time [s]') + else + set(gca,'xticklabel',[]); + end + ylabel('Energy [dB]') + set(gca,'position',[1 1 1 1.05].*get(gca,'position'),'ylim',[-70 0],'xlim',[0 max(tE_rt)]); + % choose legend according to EDT request + fitstr = num2str(abs(diff(options.y_fit))); + if nargout==5 + legend('Energy decay curve',['Linear fit (RT' fitstr ')'],'Linear fit (EDT)','location','northeast') + else + legend('Energy decay curve',['Linear fit (RT' fitstr ')'],'location','northeast') + end + end + end + % DRR + if nargout>=2 + drr(n) = 10.*log10(... + trapz(x(max(1,t0(n)-correction):t0(n)+correction,n).^2)/... + trapz(x(t0(n)+correction+1:end,n).^2)... + ); + end + % Cte + if nargout>=3 + if t0(n)+te+1>size(x,1) + warning('iosr:irStats:teOutOfRange',['Early time limit (te) out of range in channel ' num2str(n) '. Try lowering te.']) + cte(n) = NaN; + else + cte(n) = 10.*log10(... + trapz(x(max(1,t0(n)-correction):t0(n)+te).^2)/... + trapz(x(t0(n)+te+1:end,n).^2)... + ); + end + end + end + + %% write output + + switch lower(options.spec) + case 'full' + rt = rt_temp; + case 'mean' + rt = mean(rt_temp(cfs==500 | cfs==1000,:)); % overall RT + edt = mean(edt(cfs==500 | cfs==1000,:)); % overall EDT + otherwise + error('iosr:irStats:unknownSpec','Unknown ''spec'': must be ''full'' or ''mean''.') + end + +end + +function [t,E,fit] = calc_decay(z,y_fit,y_dec,fs,f) +% CALC_DECAY calculate decay time from decay curve +% Returns the time for a specified decay y_dec calculated +% from the fit over the range y_fit. The input is the +% integral of the impulse sample at fs Hz. The function also +% returns the energy decay curve in dB and the corresponding +% fit. + + E = 10.*log10(z); % put into dB + E = E-max(E); % normalise to max 0 + if any(isinf(E)) + E = E(1:find(isinf(E),1,'first')-1); % remove trailing infinite values + end + + % find yfit x-range + IX1 = findDB(E,max(y_fit),1,f); + IX2 = findDB(E,min(y_fit),length(E),f); + IX = IX1:IX2; + + % calculate fit over yfit + diff_y = abs(diff(y_fit)); % dB range diff + x = reshape(IX,1,length(IX)); + y = reshape(E(IX),1,length(IX)); + p = polyfit(x,y,1); + fitLength = max(length(E),(1.1*diff_y/abs(length(E)*p(1)))*length(E)); % evaluate fit over sufficient dynamic range + fit = polyval(p,1:fitLength); % actual fit + fit0 = fit-max(fit); % fit anchored to 0dB + t = (y_dec/diff_y)*findDB(fit0,-diff_y,[],f)/fs; % estimate decay time + fit = fit(1:length(E)); + +end + +function IX = findDB(E,dB,default,f) +% FINDDB find dB value in energy decay + + IX = find(E<=dB,1,'first'); + if isempty(IX) + if isempty(default) + error('iosr:irStats:dynamicRange','Impulse response has insufficient dynamic range at %i Hz to evaluate at %i dB.',f,dB) + else + warning('iosr:irStats:dynamicRange''Impulse response has insufficient dynamic range at %i Hz to evaluate at %i dB. Evaluating at %.1f dB instead.',f,dB,E(default)) + IX = default; + end + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+acoustics/rtEst.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+acoustics/rtEst.m new file mode 100644 index 0000000000000000000000000000000000000000..4fde07a46bacb8084b70f5f5d3d25c405d02bb90 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+acoustics/rtEst.m @@ -0,0 +1,39 @@ +function rt = rtEst(abs_coeff,room,formula) +%RTEST Estimate reverberation time based on room size and absorption +% +% RT = IOSR.ACOUSTICS.RTEST(ABS_COEFF,ROOM) estimates the reverberation +% time (RT60) for a shoebox-shaped room, with average absorption +% coefficient ABS_COEFF, and dimenions ROOM=[L W H] (in metres). An RT +% estimate is returned for each element of ABS_COEFF. +% +% RT = IOSR.ACOUSTICS.RTEST(ABS_COEFF,ROOM,FORMULA) allows the formula to +% be specified. The options are 'sabine' (default), or 'eyring'. + +% Copyright 2016 University of Surrey. + + assert(isnumeric(abs_coeff), 'iosr:rtEst:invalidCoeff', 'abs_coeff should be numeric') + assert(isnumeric(room) & numel(room)==3 & isvector(room), 'iosr:rtEst:invalidRoom', 'room should be a 3-element numeric vector') + + if nargin<3 + formula = 'sabine'; + end + + assert(ischar(formula), 'iosr:rtEst:invalidFormula', 'formula should be a character array (string)') + + l = room(1); + w = room(2); + h = room(3); + + vol = prod(room); + surf_area = (2*l*w) + (2*l*h) + (2*w*h); + + switch lower(formula) + case 'sabine' + rt = (0.161*vol)./(surf_area.*abs_coeff); + case 'eyring' + rt = (0.161*vol)./(-surf_area.*log(1-abs_coeff)); + otherwise + error('iosr:rtEst:unknownFormula','Unknown formula') + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/azimuth2itd.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/azimuth2itd.m new file mode 100644 index 0000000000000000000000000000000000000000..4a1b03a4f13a4c8dbc6aa10d1a82eaf8e7fc80c6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/azimuth2itd.m @@ -0,0 +1,26 @@ +function itd = azimuth2itd(azimuth,f) +%AZIMUTH2ITD Convert azimuth in degrees to ITD +% +% ITD = IOSR.AUDITORY.AZIMUTH2ITD(AZIMUTH,F) converts the azimuth AZIMUTH +% in degrees at frequency F to interaural time difference according to +% Kuhn's model [1]. +% +% References +% +% [1] Kuhn, G.F. (1977), Model for the interaural time differences in the +% azimuthal plane, The Journal of the Acoustical Society of America +% 62, 1, 157-167. +% +% See also IOSR.AUDITORY.ITD2AZIMUTH, IOSR.AUDITORY.FREQMULTI. + +% Copyright 2016 University of Surrey. + + assert(isnumeric(azimuth), 'iosr:azimuth2itd:invalidInput', 'AZIMUTH must be numeric') + assert((isscalar(f) | isscalar(azimuth)) | numel(f)==numel(azimuth),... + 'iosr:azimuth2itd:invalidInput', ... + 'F or ITD must be a scalar, or F and AZIMUTH must be the same size') + + czero = 344; + itd = (iosr.auditory.freqMulti(f).*0.091.*sind(azimuth))./czero; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/binSearch.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/binSearch.m new file mode 100644 index 0000000000000000000000000000000000000000..b5e29dab55d3732e6010e103bd9b3caa8d8c5acf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/binSearch.m @@ -0,0 +1,97 @@ +% Conduct a binary search +% +% binSearch: Conducts a binary search and continues until the score is +% close enough to the target. An upper limit should be set on the number of +% iterations +% +% [SearchPoint, Step, ReLoop] = iosr.auditory.binSearch(Score, ... +% TargetScore, ... +% CloseEnough, ... +% NextSearchPointa, ... +% Step, ... +% LoopCount, ... +% MaxLoops); +% end +% +% inputs: +% - Score: the test value +% - Target: the 'finished' test value +% - CloseEnough: the distance from the Target at which it is acceptable to +% discontinue the binary search +% - SearchPoint: the next work input value to try +% - Step: the distance which the SearchPoint can move by +% - LoopCount: a counter for the number of iterations completed so far +% - MaxLoops: The upper limit on the number of iterations allowed +% +% outputs: +% - SearchPoint: the next work input value you should try +% - Step: the distance which can be stepped on the NEXT iteration. You +% should store this value. +% - ReLoop: If this flag is set to 0, the upper level while loop will be +% terminated +% +% +% example: you wish to use an audibility model to find the level at which +% you can be 50% confident of detecting the signal (-+ 1%). You choose to +% start with an input level of 20dB and take no more than 10 steps of +% 40,20,10 dB etc. +% +% You would implement this in the following way: +% +% TargetPercent = 0.5; +% CloseEnough = 0.01; +% Signal Level = 40; +% Step = 40; +% MaxLoops = 10; +% LoopCount = 0; +% +% while ReLoop = 1 +% +% LoopCount = LoopCount + 1; +% +% Percent = RunAudibilityModel(SignalLevel) +% +% [SignalLevel Step ReLoop] = iosr.auditory.binSearch(Percent, ... +% TargetPercent, ... +% CloseEnough, ... +% SignalLevel, ... +% Step, ... +% LoopCount, ... +% MaxLoops); +% +% end +% + +% Copyright 2016 University of Surrey. + +function [SearchPoint, Step, ReLoop] = binSearch(Score, Target, CloseEnough, SearchPoint, Step, LoopCount, MaxLoops) + +% input tests +% test input types +assert(isnumeric(Score) ... + &isnumeric(Target) ... + &isnumeric(CloseEnough) ... + &isnumeric(SearchPoint) ... + &isnumeric(Step) ... + &isnumeric(LoopCount) ... + &isnumeric(MaxLoops),'input arguments must be numeric!'); + + +% Define next search point +if Score > Target + SearchPoint = SearchPoint - Step; +else + SearchPoint = SearchPoint + Step; +end + +% half the distance of the next step +Step = Step / 2; + +% if we got close enough to our taget, or it was the last iteration +if (abs((Score-Target))<CloseEnough)||(LoopCount>=MaxLoops) + ReLoop = 0; +else + ReLoop = 1; +end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/calcIld.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/calcIld.m new file mode 100644 index 0000000000000000000000000000000000000000..01337e8747fbebe0bfe41255948d0ec335c391ed --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/calcIld.m @@ -0,0 +1,56 @@ +function ild = calcIld(L,R,method) +%CALCILD Calculate normalised interaural level difference +% +% ILD = IOSR.AUDITORY.CALCILD(L,R) calculates the ILD of vectors L and R. +% Rather than a logarithmic ratio, the returned ILD is in the range +% [-1,1]. The algorithm has the following steps: +% +% 1. Calculate total power for each L and R vectors. +% 2. Calculate difference of powers and divide by power sum. +% 3. Square result, ensuring sign is retained. This improves contrast +% when the signals are of a similar level. +% +% ILD = IOSR.AUDITORY.CALCILD(L,R,METHOD) determines the nature of the +% ILD that is returned, and consequently how it is calculated. When +% method is 'overall' (default), the ILD for the entire signal is +% returned, based on the power carried by the fine structure. When method +% is 'vector', the ILD is calculated using the instaneous Hilbert +% envelope and the function returns a vector the same size as L or R. +% +% The function is derived from Ben Supper's thesis "An onset-guided +% spatial analyser for binaural audio" + +% Copyright 2016 University of Surrey. + + assert(isvector(L) & isvector(R), 'iosr:calcIld:invalidInput', 'L and R must be vectors') + assert(all(size(L)==size(R)), 'iosr:calcIld:invalidInput', 'L and R must be the same size') + + if nargin<3 + method='overall'; + else + assert(ischar(method), 'iosr:calcIld:invalidMethod', 'METHOD must be a string.') + end + + switch lower(method) + case 'vector' + envL = calc_env(L); + envR = calc_env(R); + p_L = envL.^2; + p_R = envR.^2; + case 'overall' + p_L = sum(L.^2); + p_R = sum(R.^2); + otherwise + error('iosr:calcIld:unknownMethod',['Unknown method ''' method '''.']) + end + ild = (p_L-p_R)./(p_L+p_R); + ild = sign(ild).*(ild.^2); + + end + +function y = calc_env(x) +%CALC_ENV return signal Hilbert envelope + + y = abs(hilbert(x)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr.m new file mode 100644 index 0000000000000000000000000000000000000000..c463ff865b250e5d1c6226bc3ed22af748f978aa --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr.m @@ -0,0 +1,250 @@ +function [ccg,ic] = chXcorr(hc_L,hc_R,fs,varargin) +%CHXCORR Calculate cross-correlograms with a wide range of options. +% +% CCG = IOSR.AUDITORY.CHXCORR(HC_L,HC_R,FS) cross-correlates the input +% 2-D matrices HC_L and HC_R over 10ms frame with a maximum lag of 1ms. +% It is assumed that the number of frequency channels is min(size(HC_L)) +% and hence HC_L and HC_R can be in either orientation. The +% cross-correlograms consist of cross-correlations for every frame and +% frequency channel. CCG has dimensions [lag,frequency,frame]. The +% function calculates running cross-correlations for every sample and +% integrates these cross-correlations over each frame. The number of +% frames frame_count is calculated thus: +% +% frame_count = ... +% floor((max(size(hc_L))-maxlag-1)/frame_length); +% +% The underlying cross-correlation algorithm is based on that proposed by +% Faller & Merimaa [1]. In this implmentation, the time constant of the +% backward infinite exponential window is given by tau (in samples). +% +% CCG = IOSR.AUDITORY.CHXCORR(HC_L,HC_R,FS,'PARAMETER',VALUE) allows a +% number of options to be specified. The options are: +% +% ({} indicates the default value) +% +% 'frame_length' : {round(0.01*fs)} | scalar +% The length of frames used to calculate for integrating +% cross-correlations. +% 'noverlap' : {1} | scalar +% The number of frames over which to integrate the +% cross-correlations. Note that the frame count is reduced +% accordingly. +% 'maxlag' : {round(0.001*fs)} | scalar +% The maximum lag of the cross-correlation. +% 'tau' : {round(0.01*fs)} | scalar +% The time constant of the exponential window used to calculate +% running cross-correlations. It is recommended that if norm_flag = 1 +% then tau >> 1. As can be seen below, as tau -> 1 then +% [aL(m,i,n?1), aR(m,i,n?1)] -> 0, and hence c(m,i,n) -> 1. +% 'inhib' : {[]} | array +% Specificies an array with which to multiply the cross-correlations +% before they are integrated. The value defaults to an empty array, +% meaning that no inhibition will be applied. +% 'ic_t' : {0} | scalar +% Specifies the interaural coherence (IC) threshold. Only samples for +% which the IC exceeds this threshold will be used to integrate +% cross-correlations. The algorithm calculates Interaural Coherence +% (IC) according to [1]. The value should be in the range [0,1]. +% 'norm_flag' : {0} | scalar +% Specifies whether the cross-correlograms are calculated using +% normalised cross-correlations. A non-zero value indicates that +% normalised cross-correlations are used. +% 'inhib_mode' : {'subtract'} | 'multiply' +% Specify how the inhibition is applied. The default 'subtract' will +% subtract inhib from the running cross-correlations (negative values +% are set to zero); 'multiply' will multiply inhib with the running +% cross-correlations. +% +% [CCG,IC] = IOSR.AUDITORY.CHXCORR(...) returns the calculated IC to the +% matrix IC. Although the matrix returned is the same size as hc_L, IC is +% only calculated for samples 1:frame_count*frame_length, other values +% will be set to 0. +% +% Algorithm +% +% The running normalised cross-correlation is calculated as [1]: +% +% C(m,i,n) = c(m,i,n) / sqrt( aL(m,i,n) * aR(m,i,n) +% +% where +% +% c(m,i,n) = (1/tau) * HC_L(i, max(n+m,n)) * HC_R(i, max(n-m,n)) + ... +% (1-1/tau) * c(m,i,n-1), +% +% aL(m,i,n) = (1/tau) * (HC_L(i, max(n+m,n)))^2 + ... +% (1-1/tau) * aL(m,i,n-1), +% +% aR(m,i,n) = (1/tau) * (HC_R(i, max(n+m,n)))^2 + ... +% (1-1/tau) * aR(m,i,n-1), +% +% i is the frequency index, m is the lag index, and n is the sample +% index. The running (non-normalised) cross-correlation is calculated is +% simply c(m,i,n). +% +% The interaural coherence is +% +% IC(i,n) = max(C(m,i,n)) % (i.e. over m) +% +% The cross-correlogram is calculated as the sum of cross- correlations +% in a given frame: +% +% CCG(m,i,j) = sum(C(m,i,J),3) +% +% where +% +% J = (j-1) * frame_length + 1 : j * frame_length +% +% References +% +% [1] C. Faller and J. Merimaa, "Source localization in complex listening +% situations: Selection of binaural cues based on interaural +% coherence", The Journal of the Acoustical Society of America, vol. +% 116, pp.3075-3089, Nov. 2004. +% +% Further Reading +% +% C. Hummersone, R. Mason, and T. Brookes, "A comparison of computational +% precedence models for source separation in reverberant +% environments", The Journal of the Audio Engineering Society, vol. +% 61(7/8), pp.508-520, July 2013. + +% Copyright 2016 University of Surrey. + + assert(nargin>=3, 'iosr:chXcorr:nargin', 'Number of input arguments must be greater than or equal to three.') + + if isparameter(varargin,'inhib_mode') && ~isparameter(varargin,'inhib') + warning('iosr:instIld:inhibMode','''inhib_mode'' specified, but no inhibition array ''inhib''.'); + end + + % Check source file is compiled + iosr.general.checkMexCompiled('-largeArrayDims',fullfile(fileparts(mfilename('fullpath')),'chXcorr_c.c')) + + options = struct(... + 'frame_length',round(0.01*fs),... + 'noverlap',1,... + 'maxlag',round(0.001*fs),... + 'tau',round(0.01*fs),... + 'inhib',[],... + 'ic_t',0,... + 'norm_flag',0,... + 'inhib_mode','subtract'); + + % read parameter/value inputs + if nargin > 3 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:chXcorr:nameValuePair','CHXCORR needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:chXcorr:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % assign options to variables + frame_length = options.frame_length; + noverlap = options.noverlap; + maxlag = options.maxlag; + tau = options.tau; + inhib_mode = options.inhib_mode; + norm_flag = options.norm_flag; + ic_t = options.ic_t; + inhib = options.inhib; + + % check inputs + assert(all(size(hc_L)==size(hc_R)), 'iosr:chXcorr:invalidInput', '''hc_L'' and ''hc_R'' must be the same size') + assert(round(frame_length)==frame_length && isscalar(frame_length) && frame_length>0, 'iosr:chXcorr:invalidFrame', ... + '''frame_length'' must be an integer greater than zero') + assert(round(noverlap)==noverlap && isscalar(noverlap) && noverlap>0, 'iosr:chXcorr:invalidNoverlap', ... + '''noverlap'' must be an integer greater than zero') + assert(round(maxlag)==maxlag && isscalar(maxlag) && maxlag>0, 'iosr:chXcorr:invalidMaxlag', ... + '''maxlag'' must be an integer greater than zero') + assert(isscalar(tau) && tau>=1, 'iosr:chXcorr:invalidTau', '''tau'' must be a scalar greater than or equal to one') + assert(isscalar(norm_flag), 'iosr:chXcorr:invalidNorm', '''norm_flag'' must be a scalar') + assert(isscalar(ic_t) && ic_t>=0 && ic_t<=1, 'iosr:chXcorr:invalidIct', '''ic_t'' must be a scalar in the range [0,1]') + assert(ischar(inhib_mode), 'iosr:chXcorr:invalidInhibMode', '''inhib_mode'' must be a char array (string)') + + % Calculate frame count + frame_count = floor(max(size(hc_L))/(frame_length)); + frame_count = frame_count-noverlap+1; + + % Calculate number of frequency channels + numchans = min(size(hc_L)); + numsamples = max(size(hc_L)); + + % Check orientation of HC and inhib data (i.e. that frequency runs across the rows) + dims = size(hc_L); + hc_L = check_input(hc_L,2,numchans); + hc_R = check_input(hc_R,2,numchans); + + % set a flag if data has been transposed in this way + if dims(1)~=size(hc_L,1) + rot = true; + else + rot = false; + end + + % set inhibition mode ID + switch inhib_mode + case 'multiply' + inhib_mode_ID = 1; + if isempty(inhib) + inhib = ones(size(hc_L)); + end + case 'subtract' + inhib_mode_ID = 2; + if isempty(inhib) + inhib = zeros(size(hc_L)); + end + otherwise + error('iosr:chXcorr:unknownInhibMode','''inhib_mode'' must be set to ''multiply'' or ''subtract''') + end + + inhib = check_input(inhib,2,numchans); + + % Append HC and inhibition data with zeros for cross-correlation + hc_L = [hc_L; zeros(maxlag+1,numchans)]; + hc_R = [hc_R; zeros(maxlag+1,numchans)]; + inhib = [inhib; zeros(maxlag+1,numchans)]; + + assert(all(size(inhib)==size(hc_L)), 'iosr:chXcorr:invalidInhib', '''inhib'' must be a matrix the same size as ''hc_L'' or ''hc_R''') + + % Calculate cross-correlograms + [ccg,ic] = iosr.auditory.chXcorr_c(hc_L,hc_R,frame_count,frame_length,noverlap,maxlag,tau,inhib,ic_t,norm_flag,inhib_mode_ID); + + % Correct orientation of IC data, if data was transposed, and crop to remove appended zeros + ic = ic(1:numsamples,:); + if rot + ic = ic'; + end + +end + +function output = check_input(input,dim,target) +%CHECK_INPUT check input is correct orientation + + if size(input,dim)~=target + output = input'; + assert(size(output,dim)==target, 'iosr:chXcorr:invalidInputs', 'Input invalid') + else + output = input; + end + +end + +function set = isparameter(input,parameter) +%ISPARAMETER check for input parameter + + set = any(strcmpi(input(cellfun(@ischar,input)),parameter)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr2.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr2.m new file mode 100644 index 0000000000000000000000000000000000000000..82a2b21892b2d9e54f3d8f06afac91126e7e6a3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr2.m @@ -0,0 +1,128 @@ +function [ccg,ic] = chXcorr2(hc_L,hc_R,fs,varargin) +%CHXCORR2 Calculate cross-correlograms with a range of options. +% +% CCG = IOSR.AUDITORY.CHXCORR2(HC_L,HC_R,FS) cross-correlates the input +% 2-D matrices HC_L and HC_R over 10ms frame with a maximum lag of 1ms. +% It is assumed that the number of frequency channels is min(size(HC_L)) +% and hence HC_L and HC_R can be in either orientation. The +% cross-correlograms consist of cross-correlations for every frame and +% frequency channel. CCG has dimensions [lag,frequency,frame]. The +% function calculates the traditional cross-correlation in each frame. +% The number of frames FRAME_COUNT is calculated thus: +% +% FRAME_COUNT = FIX((MAX(SIZE(HC_L)))/FRAME_LENGTH); +% +% CCG = IOSR.AUDITORY.CHXCORR2(HC_L,HC_R,FS,'PARAMETER',VALUE) allows a +% number of options to be specified. The options are: +% +% ({} indicates the default value) +% +% 'frame_length' : {round(0.01*fs)} | scalar +% The length of frames (in samples) used for calculating +% cross-correlations. +% 'hop' : {[]} | scalar +% The hop size (in samples). By default the hop size is equal to the +% frame length (HOP is specified as an empty array). The hop size +% determines the number of frames as +% FIX((MAX(SIZE(HC_L))-(FRAME_LENGTH-HOP))/HOP); +% 'maxlag' : {round(0.001*fs)} | scalar +% The maximum lag of the cross-correlation (in samples). +% 'norm_flag' : {0} | scalar +% Specifies whether the cross-correlograms are calculated using +% normalised cross-correlations. A non-zero value indicates that +% normalised cross-correlations are used. +% +% [CCG,IC] = IOSR.AUDITORY.CHXCORR2(...) returns the calculated IC for +% each frame to the matrix IC. + +% Copyright 2016 University of Surrey. + + assert(nargin>=3, 'iosr:chXcorr2:nargin', 'Number of input arguments must be greater than or equal to three.') + + % Check source file is compiled + iosr.general.checkMexCompiled('-largeArrayDims',fullfile(fileparts(mfilename('fullpath')),'chXcorr2_c.c')) + + options = struct(... + 'frame_length',round(0.01*fs),... + 'maxlag',round(0.001*fs),... + 'norm_flag',0,... + 'hop',[]); + + % read parameter/value inputs + if nargin > 3 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:chXcorr2:nameValuePair','CHXCORR2 needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:chXcorr2:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % assign options to variables + frame_length = options.frame_length; + maxlag = options.maxlag; + norm_flag = options.norm_flag; + if isempty(options.hop) + hop = frame_length; + else + hop = options.hop; + end + + % check inputs + assert(all(size(hc_L)==size(hc_R)), 'iosr:chXcorr2:invalidInput', '''hc_L'' and ''hc_R'' must be the same size') + assert(round(frame_length)==frame_length && isscalar(frame_length) && frame_length>0, ... + 'iosr:chXcorr2:invalidFrame', '''frame_length'' must be an integer greater than zero') + assert(round(maxlag)==maxlag && isscalar(maxlag) && maxlag>0, 'iosr:chXcorr2:invalidMaxlag', ... + '''maxlag'' must be an integer greater than zero') + assert(isscalar(norm_flag), 'iosr:chXcorr2:invalidNorm', '''norm_flag'' must be a scalar') + + % Calculate frame count + frame_count = fix((max(size(hc_L))-(frame_length-hop))/hop); + + % Calculate number of frequency channels + numchans = min(size(hc_L)); + + % Check orientation of HC and inhib data (i.e. that frequency runs across the rows) + dims = size(hc_L); + hc_L = check_input(hc_L,2,numchans); + hc_R = check_input(hc_R,2,numchans); + + % set a flag if data has been transposed in this way + if dims(1)~=size(hc_L,1) + rot = true; + else + rot = false; + end + + % Calculate cross-correlograms + [ccg,ic] = iosr.auditory.chXcorr2_c(hc_L,hc_R,frame_count,frame_length,maxlag,hop,norm_flag); + + % Correct orientation of IC data, if data was transposed, and crop to remove appended zeros + if rot + ic = ic'; + end + +end + +function output = check_input(input,dim,target) +%CHECK_INPUT check input is correct orientation + + if size(input,dim)~=target + output = input'; + assert(size(output,dim)==target, 'iosr:chXcorr2:invalidInput', 'Input invalid') + else + output = input; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr2_c.c b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr2_c.c new file mode 100644 index 0000000000000000000000000000000000000000..ab6d63e7d39c827caad0dcc632173a098a8c59ff --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr2_c.c @@ -0,0 +1,197 @@ +/* + * Calculate cross-correlograms with a range of options. + * Called from chXcorr2.m. + * + * Copyright 2016 University of Surrey. + * + */ + +#include "math.h" +#include "mex.h" +#include "matrix.h" + +#define max(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a > _b ? _a : _b; }) + +/* structure for cross-correlation info */ +struct xcorr +{ + int maxlag; + double ic; + double *c; + double *nc; + double *aL; + double *aR; +}; + +/* cross-correlation functions */ +void xcorr(double L[], double R[], int frame_length, int numsamples, struct xcorr * data); +void initXcorr(unsigned int maxlag, unsigned int length, struct xcorr * data); +void freeXcorr(struct xcorr * data); + +/* main function */ +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + /* ====================== DECLARATIONS ====================== */ + + double + *hc_L = mxGetPr(prhs[0]), /* input left signal */ + *hc_R = mxGetPr(prhs[1]), /* input right signal */ + *cout; /* output */ + + int + frame_count = *mxGetPr(prhs[2]), /* Input number of frames in input */ + frame_length = *mxGetPr(prhs[3]), /* Frame length */ + maxlag = *mxGetPr(prhs[4]), /* Maximum lag for cross-correlation */ + hop = *mxGetPr(prhs[5]), /* hop size */ + norm_flag = *mxGetPr(prhs[6]), /* normalisation flag */ + lengthCCG = (2*maxlag)+1; /* Cross-correlation length */ + + mwSize + numsamples = mxGetM(prhs[0]), /* Number of samples in HC data */ + numchans = mxGetN(prhs[0]); /* Number of frequency channels in input HC data */ + + /* Indices */ + mwIndex + m, /* lag index */ + i, /* Frequency channel index */ + j, /* Frame index */ + sample, /* sample index */ + index_ccg, /* Index to CCG */ + index_ic; /* index into interaural coherence */ + + /* cross-correlation data */ + struct xcorr ccdata; + initXcorr(maxlag, lengthCCG, &ccdata); + + /* choose output according to normalisation */ + if (norm_flag == 0) { + cout = ccdata.c; + } + else { + cout = ccdata.nc; + } + + /* ====================== OUTPUTS ====================== */ + + mwSize ccg_dims[3] = {(mwSize)lengthCCG, numchans, (mwSize)frame_count}; /* CCG dimensions */ + plhs[0] = mxCreateNumericArray(3,ccg_dims,mxDOUBLE_CLASS,mxREAL); + plhs[1] = mxCreateDoubleMatrix(frame_count,numchans,mxREAL); + double *ccg_out = mxGetPr(plhs[0]), + *ic_out = mxGetPr(plhs[1]); + + /* ====================== CROSS-CORRELATE ====================== */ + for ( j = 0; j < frame_count; j++ ) { + for ( i = 0; i < numchans; i++ ) { + /* indices */ + sample = (i*(mwIndex)numsamples)+(j*(mwIndex)hop); + index_ccg = (i*lengthCCG)+(j*lengthCCG*numchans); + index_ic = (i*(mwIndex)frame_count)+j; + /* cross-correlate */ + xcorr(hc_L+sample, hc_R+sample, frame_length, numsamples, &ccdata); + /* outputs */ + ic_out[index_ic] = ccdata.ic; + for ( m = 0; m < lengthCCG; m++ ) { + ccg_out[index_ccg+m] = cout[m]; + } + } /* end frequency loop */ + } /* end frame loop */ + /* Destroy arrays */ + freeXcorr(&ccdata); + return; +} + +void xcorr(double L[], double R[], int frame_length, int numsamples, struct xcorr * data) +{ + + int m, /* lag index */ + n, /* sample index */ + maxlag = data->maxlag; /* maximum cross-correlation lag */ + double + Rshift, /* shifted right signal */ + mL = 0.0, /* mean of left */ + mR = 0.0, /* mean of right */ + denom, /* denominator */ + *c = data->c, /* cross-correlation */ + *nc = data->nc, /* normalised cross-correlation */ + *aL = data->aL, /* left variance */ + *aR = data->aR, /* right variance */ + *ic = &(data->ic); /* interaural coherence */ + + /* reset arrays to 0 */ + for (m = 0; m < 2*maxlag+1; m++) { + c[m] = 0.0; + nc[m] = 0.0; + aL[m] = 0.0; + aR[m] = 0.0; + } + + /* calculate mean of time series */ + for (n = 0; n < frame_length; n++) { + mL += L[n]/frame_length; + mR += R[n]/frame_length; + } + + /* calculate cross-correlations of time series */ + for (m = -maxlag; m <= maxlag; m++) { + for (n = 0; n < frame_length; n++) { + /* do not wrap, but set out-of-bounds to zero */ + if (((n-m) < 0) || ((n-m) > frame_length) || ((n-m) > numsamples)) { + Rshift = 0.0; + } + else { + Rshift = R[n-m]; + } + /* cross-correlate */ + c[m+maxlag] += (L[n]-mL) * (Rshift-mR); /* cross-correlation */ + aL[m+maxlag] += pow(L[n]-mL,2.0); /* variance of left */ + aR[m+maxlag] += pow(Rshift-mR,2.0); /* variance of right */ + } + } + + /* normalise the cross-correlation */ + data->ic = 0.0; /* reset to 0 */ + for (m = 0; m < 2*maxlag+1; m++) { + denom = sqrt(aL[m])*sqrt(aR[m]); /* denominator */ + if (denom > 0.0) { + nc[m] = c[m]/denom; + } + else { /* prevent divide by zero */ + nc[m] = 0.0; + } + /* calculate coherence */ + *ic = max(*ic,nc[m]); + } + + return; + +} + +void initXcorr(unsigned int maxlag, unsigned int length, struct xcorr * data) +{ + /* initialise and allocate data */ + data->maxlag = maxlag; + data->ic = 0.0; + data->c = calloc(length,sizeof(double)); + data->nc = calloc(length,sizeof(double)); + data->aL = calloc(length,sizeof(double)); + data->aR = calloc(length,sizeof(double)); + if (length != 0 && (!data->c || !data->nc || !data->aL || !data->aR)) { + freeXcorr(data); + } +} + +void freeXcorr(struct xcorr * data) +{ + /* free memory */ + if (data->c) + free(data->c); + if (data->nc) + free(data->nc); + if (data->aL) + free(data->aL); + if (data->aR) + free(data->aR); +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr_c.c b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr_c.c new file mode 100644 index 0000000000000000000000000000000000000000..67acf5912356ec84c2d6990051b7d07b99a5977d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/chXcorr_c.c @@ -0,0 +1,205 @@ +/* + * Calculate cross-correlograms with a wide range of options. + * Called from chXcorr.m. + * + * Copyright 2016 University of Surrey. + * + */ + +#include "math.h" +#include "mex.h" +#include "matrix.h" + +#define INHIB_MULTIPLY 1 +#define INHIB_SUBTRACT 2 + +#define MAX(A,B) ((A)>(B) ? (A) : (B)) + +#define A_TEMP_ARRAY mxCreateDoubleMatrix((mwSize)lengthCCG,numchans,mxREAL) +#define CCG_TEMP_ARRAY mxCreateNumericArray((mwSize)3,ccg_r_dims,mxDOUBLE_CLASS,mxREAL) + +double xcorr(double L, double R, double prev, double tc) { + return ((1.0/tc)*L*R) + ((1.0-(1.0/tc))*prev); +} + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + /* ====================== DECLARATIONS ====================== */ + + double *hc_L = mxGetPr(prhs[0]), /* input left signal */ + *hc_R = mxGetPr(prhs[1]); /* input right signal */ + + int frameCount = *mxGetPr(prhs[2]), /* Input number of frames in input */ + frame_length = *mxGetPr(prhs[3]), /* Frame length */ + noverlap = *mxGetPr(prhs[4]), /* Number of frames to overlap in CCG calculations */ + maxlag = *mxGetPr(prhs[5]); /* Maximum lag for cross-correlation */ + + double tau = *mxGetPr(prhs[6]), /* Time constant for cross-correlation calculation */ + *inhib = mxGetPr(prhs[7]), /* Inhibition data */ + ic_t = *mxGetPr(prhs[8]); /* Interaural coherence threshold */ + + int norm_flag = *mxGetPr(prhs[9]), /* Normalisation flag: 0 = no normalisation, any other value indicates normalisation */ + inhib_mode_ID = *mxGetPr(prhs[10]); /* Inhibition mode: 1 = multiplication, 2 = subtraction */ + + mwSize numsamples = mxGetM(prhs[0]), /* Number of samples in HC data */ + numchans = mxGetN(prhs[0]); /* Number of frequency channels in input HC data */ + + /* The IC for the cross-correlation at the current sample */ + double ic; + + int ic_count = 0, /* Counts number of samples over IC_T */ + lengthCCG = (2*maxlag)+1, /* Cross-correlation length */ + lookahead = 0; /* Number of frames to look ahead for CCG calculation */ + + /* Indices */ + mwIndex i, /* Frequency channel index */ + j, /* Frame index */ + n, /* Sample index */ + m, /* Lag index */ + sample, /* sample index */ + ic_sample, /* IC sample index */ + index_ccg_r, /* Running cross-correlation index */ + index_ccg_r_ahead, /* Running cross-correlation index for look ahead frame */ + index_a, /* Index to auto- and cross-correlations */ + index_ccg, /* Index to CCG */ + leftn, /* Left index for calculating cross-correlations */ + rightn; /* Right index for calculating cross-correlations */ + + /* Dimensions */ + mwSize ccg_dims[3] = {(mwSize)lengthCCG, numchans, (mwSize)frameCount}, /* CCG dimensions */ + ccg_r_dims[3] = {(mwSize)lengthCCG, (mwSize)frame_length*noverlap, numchans}; /* Running cross-correlation dimensions */ + + /* ====================== TEMP ARRAYS ====================== */ + + /* Running auto- and cross-correlations for previous sample */ + mxArray *a_LL_prev_mx,*a_RR_prev_mx,*a_LR_prev_mx; + a_LL_prev_mx = A_TEMP_ARRAY; + a_RR_prev_mx = A_TEMP_ARRAY; + a_LR_prev_mx = A_TEMP_ARRAY; + double *a_LL_prev = mxGetPr(a_LL_prev_mx), + *a_RR_prev = mxGetPr(a_RR_prev_mx), + *a_LR_prev = mxGetPr(a_LR_prev_mx); + + /* Running auto- and cross-correlations */ + mxArray *a_LL_mx,*a_RR_mx,*a_LR_mx; + a_LL_mx = A_TEMP_ARRAY; + a_RR_mx = A_TEMP_ARRAY; + a_LR_mx = A_TEMP_ARRAY; + double *a_LL = mxGetPr(a_LL_mx), + *a_RR = mxGetPr(a_RR_mx), + *a_LR = mxGetPr(a_LR_mx); + + /* Cross-correlations */ + mxArray *ccg_norm_mx, *ccg_r_mx, *ccg_ic_mx; + ccg_norm_mx = CCG_TEMP_ARRAY; + ccg_r_mx = CCG_TEMP_ARRAY; + ccg_ic_mx = mxCreateDoubleMatrix((mwSize)lengthCCG,(mwSize)1,mxREAL); + double ccg_ic_temp, + *ccg_norm = mxGetPr(ccg_norm_mx), + *ccg_r = mxGetPr(ccg_r_mx), + *ccg_ic = mxGetPr(ccg_ic_mx); + + /* ====================== OUTPUTS ====================== */ + + plhs[0] = mxCreateNumericArray(3,ccg_dims,mxDOUBLE_CLASS,mxREAL); + plhs[1] = mxCreateDoubleMatrix(numsamples,numchans,mxREAL); + double *ccg_out = mxGetPr(plhs[0]), + *ic_out = mxGetPr(plhs[1]); + + /* ====================== CROSS-CORRELATE ====================== */ + for ( j = 0; j < frameCount; j++ ) { + for ( i = 0; i < numchans; i++ ) { + index_ccg = (i*lengthCCG)+(j*lengthCCG*numchans); + sample = (i*(mwIndex)numsamples)+((j+lookahead)*(mwIndex)frame_length); + ic_sample = (i*(mwIndex)numsamples)+(j*(mwIndex)frame_length); + for ( m = 0; m < lengthCCG; m++ ) {/* reset ccg for T-F unit */ + ccg_ic[m] = 0.0; + } + /* Calculate raw cross-correlations */ + for ( n = 0; n < frame_length*(noverlap-lookahead); n++ ) { + index_a = (i*lengthCCG); + index_ccg_r = ((n+(lookahead*frame_length))+i*(noverlap*frame_length))*lengthCCG; + ic = 0.0; /* reset the IC value for the sample */ + for ( m = 0; m < lengthCCG; m++ ) { /* calculate cross-correlations */ + leftn = sample+n+( (m>maxlag) ? (m-maxlag) : (0) ); + rightn = sample+n+( (m<maxlag) ? (maxlag-m) : (0) ); + a_LR[index_a+m] = xcorr(hc_L[leftn],hc_R[rightn],a_LR_prev[index_a+m],tau); + a_LL[index_a+m] = xcorr(hc_L[leftn],hc_L[leftn],a_LL_prev[index_a+m],tau); + a_RR[index_a+m] = xcorr(hc_R[rightn],hc_R[rightn],a_RR_prev[index_a+m],tau); + ccg_norm[index_ccg_r+m] = a_LR[index_a+m]/sqrt(a_LL[index_a+m]*a_RR[index_a+m]); + if ( (a_LL[index_a+m]*a_RR[index_a+m])==0.0 ) { /* prevent divide by zero */ + ccg_norm[index_ccg_r+m] = 0.0; + } + ic = MAX(ic,ccg_norm[index_ccg_r+m]); /* calculate IC for sample (as max) */ + if ( norm_flag == 0 ) { + /* Un-normalised */ + ccg_r[index_ccg_r+m] = a_LR[index_a+m]; + } + else { + /* Normalised */ + ccg_r[index_ccg_r+m] = ccg_norm[index_ccg_r+m]; + } + /* Set cross-correlations for what will become the previous sample */ + a_LR_prev[index_a+m] = a_LR[index_a+m]; + a_LL_prev[index_a+m] = a_LL[index_a+m]; + a_RR_prev[index_a+m] = a_RR[index_a+m]; + } + ic_out[sample+n] = ic; /* Write IC to output */ + } + ic_count = 0; /* reset the count of samples with IC values over the IC threshold */ + /* Integrate cross-correlations */ + for ( n = 0; n < frame_length*noverlap; n++ ) { + index_ccg_r = (n+i*(frame_length*noverlap))*lengthCCG; + if ( ic_out[ic_sample+n] >= ic_t ) { /* check if IC exceeds IC threshold */ + ic_count++; /* count the number of samples that exceed the IC threshold */ + for ( m = 0; m < lengthCCG; m++ ) { /* inhibit (multiplication) */ + switch (inhib_mode_ID) { + case INHIB_MULTIPLY: + ccg_ic[m] += ccg_r[index_ccg_r+m]*inhib[sample+n]; + break; + case INHIB_SUBTRACT: + ccg_ic_temp = ccg_r[index_ccg_r+m]-((1.0/tau)*inhib[sample+n]); + ccg_ic[m] += MAX(ccg_ic_temp,0.0); + break; + default: + mexErrMsgTxt("Unknown inhib_mode_ID"); + } + } + } + else { + ic_out[ic_sample+n] = 0; + } + } + if ( ic_count == 0 ) { /* write zeros to output if no samples in frame have high enough IC */ + for ( m = 0; m < lengthCCG; m++ ) { + ccg_out[index_ccg+m] = 0.0; + } + } + else { /* average CCGs with high enough IC */ + for ( m = 0; m < lengthCCG; m++ ) { + ccg_out[index_ccg+m] = ccg_ic[m]/(double)ic_count; /* Write CCG to output */ + } + } + /* move ccg_r's backwards to append for subsequent frames */ + for ( n = 0; n < frame_length*(noverlap-1); n++ ) { + index_ccg_r = (n+i*(frame_length*noverlap))*lengthCCG; + index_ccg_r_ahead = ((n+frame_length)+i*(frame_length*noverlap))*lengthCCG; + for ( m = 0; m < lengthCCG; m++ ) { + ccg_r[index_ccg_r+m] = ccg_r[index_ccg_r_ahead+m]; + } + } + } /* end frequency loop */ + lookahead = noverlap-1; /* Set value */ + } /* end frame loop */ + /* Destroy mx arrays */ + mxDestroyArray(ccg_norm_mx); + mxDestroyArray(ccg_r_mx); + mxDestroyArray(ccg_ic_mx); + mxDestroyArray(a_LL_mx); + mxDestroyArray(a_RR_mx); + mxDestroyArray(a_LR_mx); + mxDestroyArray(a_LL_prev_mx); + mxDestroyArray(a_RR_prev_mx); + mxDestroyArray(a_LR_prev_mx); + return; +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/createWindow.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/createWindow.m new file mode 100644 index 0000000000000000000000000000000000000000..33ba7ae585fd58550669ea0e6c0e4e012e2b8ee2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/createWindow.m @@ -0,0 +1,186 @@ +function OutWin = createWindow(varargin) +% Create a Hann or exp. window with specified onsets/offsets +% +% OutWin = iosr.auditory.createWindow(WinLen, Type, Duration) +% +% Other (non-symmetric) uses include: +% +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Hann, ... +% OnDuration, ... +% Hann, ... +% OffDuration,) +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Hann, ... +% OnDuration, ... +% Exp, ... +% OffDuration, ... +% OffSlope) +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Exp, ... +% OnDuration, ... +% OnSlope, ... +% Hann, ... +% OffDuration) +% OutWin = iosr.auditory.createWindow(WinLen, ... +% Exp, ... +% OnDuration, ... +% OnSlope, ... +% Exp, ... +% OffDuration, ... +% OffSlope) +% +% OutWin = iosr.auditory.createWindow(type, samples) +% OutWin = iosr.auditory.createWindow(Ontype, Onsamples, ... +% Offtype, Offsamples) +% +% In the first mode of operation, the onset and offset are assumed to be +% identical (symmetric window). In other modes, the OnRamp and OffRamp +% durations (and slopes if necessary) are specified independently +% +% OutWin: the created window +% +% WinLen: the total duration (in samples) of the desired window +% +% Type (inc. Ontype and Offtype): +% +% - 'Hann': a raised cosine ramp, following value should always be the +% Duration of the ramp +% +% - 'Exp': an exponential ramp, following value should be always be the +% Duration of the ramp, and then the Slope. e.g Slope > 3 very shallow, +% slope < 0.1 very steep +% +% Duration: number of samples over which the OnRamp and OffRamp are applied +% +% Slope: the steepness of the exponential ramp +% +% Example case: 100 samples onset Hann, followed by 50 unramped samples +% (i.e. value = 1), followed by 500 samples of shallow exponential offset +% ramp +% +% OutWin = iosr.auditory.createWindow(650, 'Hann', 100, 'Exp', 500, 3) + +% Copyright 2016 University of Surrey. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Begin Create Window +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%% test input types +assert(isnumeric(varargin{1}),['1st input should be window length' ... +'specified in samples']); +assert(size(varargin, 2)>2,'not enough input arguments'); +assert(size(varargin, 2)<8,'too many input arguments'); + +%% extract inputs +nInputs = (size(varargin, 2)); +WinLen = varargin{1}; +Slope = [0 0]; +switch nInputs + + case 3 % Hann or Rec symmetric window + assert(~strcmp(varargin{2},('Exp')),'Must specify slope of exponential'); + assert(strcmp(varargin{2},('Hann')) || strcmp(varargin{2},('Rec')),'Input type not specified'); + RampOn = varargin{2}; + RampOff = varargin{2}; + RampOnDur = varargin{3}; + RampOffDur = varargin{3}; + case 4 % Exp symmetric window + assert(strcmp(varargin{2},('Exp')),'wrong number of input arguments or ramp type'); + assert(varargin{4}~=0,'exponential slope may not be 0'); + RampOn = 'Exp'; + RampOff = 'Exp'; + RampOnDur = varargin{3}; + RampOffDur = varargin{3}; + Slope(1) = varargin{4}; + case 5 % Hann or Rec ramp on and ramp off + assert(strcmp(varargin{2},('Hann')) || strcmp(varargin{2},('Rec')),'Input type not specified'); + assert(strcmp(varargin{4},('Hann')) || strcmp(varargin{4},('Rec')),'Input type not specified'); + RampOn = varargin{2}; + RampOff = varargin{4}; + RampOnDur = varargin{3}; + RampOffDur = varargin{5}; + case 6 % (Hann or Rec) + Exp, or Exp + (Hann or Rec) + if (strcmp(varargin{2},'Hann')||strcmp(varargin{2},'Rec')) + RampOn = varargin{2}; + RampOnDur = varargin{3}; + RampOff = 'Exp'; + RampOffDur = varargin{5}; + Slope(2) = varargin{6}; + elseif strcmp(varargin{2},'Exp') + RampOn = 'Exp'; + RampOnDur = varargin{3}; + assert(isnumeric(varargin{4}),'exponential slope should be specified as arg 4'); + assert(varargin{4}~=0,'exponential slope may not be 0'); + Slope(1) = varargin{4}; + RampOff = varargin{5}; + RampOffDur = varargin{6}; + else + error('incorrect input arguments'); + end +case 7 % Ramp on = Exp, Ramp off = Exp + assert(strcmp(varargin{2},('Exp')) && strcmp(varargin{2},('Exp')),'both ramps should be Exp for 7 input arguments'); + RampOn = 'Exp'; + RampOff = 'Exp'; + RampOnDur = varargin{3}; + Slope(1) = varargin{4}; + RampOffDur = varargin{6}; + Slope(2) = varargin{7}; + otherwise + error('incorrect number of inputs'); +end +assert(WinLen>=((RampOnDur)+(RampOffDur)),'ramp lengths greater than signal duration!'); + +%% Test Hann gives correct answer for dummy example +assert( 0.01 > ( max(abs( AppWin(100,'Hann',10,'Hann',10) - ... + [ 0; 0.0245; 0.0955; 0.2061; 0.3455; 0.5000; ... + 0.6545; 0.7939; 0.9045; 0.9755; ... + ones(80,1); ... + 0.9755; 0.9045; 0.7939; 0.6545; 0.5000; ... + 0.3455; 0.2061; 0.0955; 0.0245; 0 ]))), ... + 'Hann not functioning corectly'); + +%% Do Work +OutWin = AppWin(WinLen,RampOn,RampOnDur,RampOff,RampOffDur,Slope); + +end + +% ---------------------------------------------------------- +% DO AppWin +% ---------------------------------------------------------- +function OutWin = AppWin(WinLen,RampOn,RampOnDur,RampOff,RampOffDur,Slope) + +% generate rectangular window +OutWin = ones(WinLen,1); + +%% Create the ramp on +switch RampOn + case 'Hann' + OutWin(1:RampOnDur) = (1-cos(pi/RampOnDur*[0:RampOnDur-1])) / 2; + + case 'Exp' + OutWin(1:RampOnDur) = exp(([1:RampOnDur]./(Slope(1)*RampOnDur))-(1/Slope(1))); + + case 'Rec' + + otherwise + error('ramp on unspecified'); +end + +%% Create the ramp off +switch RampOff + case 'Hann' + OutWin(end-RampOffDur+1:end) = (1+cos(pi/RampOffDur*[1:RampOffDur]))/2; + + case 'Exp' + OutWin(end-RampOffDur+1:end) = exp((fliplr([1:RampOffDur])./(Slope(2)*RampOffDur))-(1/Slope(2))); + + case 'Rec' + + otherwise + error('ramp off unspecified'); +end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/dupWeight.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/dupWeight.m new file mode 100644 index 0000000000000000000000000000000000000000..ee2ebb54c90258704406119cc3501a4dd6bae906 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/dupWeight.m @@ -0,0 +1,67 @@ +function [w_itd,w_ild] = dupWeight(f) +%DUPWEIGHT Calculate duplex weighting coefficients for ITD and ILD +% +% [W_ITD,W_ILD] = IOSR.AUDITORY.DUPWEIGHT(F) returns the weighting +% coefficients for ITD W_ITD and ILD W_ILD for frequency F (Hz). +% +% The function is derived from Ben Supper's thesis "An onset-guided +% spatial analyser for binaural audio", with some necessary +% modifications. Specifically, his work accounts for the ITD dominance +% condition. This function does not, as this cannot be derived from the +% work, since the work assumes an upper frequency limit of 13750 Hz +% (which cannot be assumed in this function). The quadratic ramp in ITD +% weighting is approximated linearly here. +% +% The input f may be an array of any size. The outputs will be the same +% size as f, with coefficients calculated for each element. +% +% See also IOSR.AUDITORY.LOUDWEIGHT. + +% Copyright 2016 University of Surrey. + + %% Check input + + assert(all(f(:)>=0), 'iosr:functionalBoxPlot:invalidF', 'f should be greater than or equal to zero!') + + if any(f(:)>20000) + warning('iosr:dupWeight:frequencyRange','Humans cannot generally hear above 20 kHz. Weighting coefficients will be set to zero.') + end + + %% Calculate original weights using Ben's numbers + + % Frequency scale in Ben's thesis + freq_scale = [60 150 250 350 455 570 700 845 1000 1175 ... + 1375 1600 1860 2160 2510 2925 3425 4050 4850 5850 ... + 7050 8600 10750 13750]; + + % Corresponding bin numbers + b = 1:24; + + % frequency ranges (indices) + low = b<=8; % below cross-over region + mid = b>8 & b<14; % cross-over region + high = b>=14; % above cross-over region + + % pre-allocate outputs + w_itd_orig = zeros(size(freq_scale)); + w_ild_orig = zeros(size(freq_scale)); + + % Do maths + w_itd_orig(low) = 1.597-(0.047*b(low)); + w_itd_orig(mid) = (0.0102.*(b(mid).^2))-(0.437.*b(mid))+4.06; + w_itd_orig(high) = 0.11; + % + w_ild_orig(low) = 0.2; + w_ild_orig(mid) = (0.152.*b(mid))-1.016; + w_ild_orig(high) = 0.96; + + %% Calculate weights for input frequencies + + % ...via interpolation + w_itd = interp1(freq_scale,w_itd_orig,f,'pchip','extrap'); + w_ild = interp1(freq_scale,w_ild_orig,f,'pchip','extrap'); + + w_itd(f>20000) = 0; + w_ild(f>20000) = 0; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/erbRate2hz.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/erbRate2hz.m new file mode 100644 index 0000000000000000000000000000000000000000..5fca853d1c28eb0d1e122e995cebc5a4d06049a1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/erbRate2hz.m @@ -0,0 +1,13 @@ +function y=erbRate2hz(x) +%ERBRATE2HZ Convert ERB rate to Hz. +% +% Y = IOSR.AUDITORY.ERBRATE2HZ(X) converts the ERB number X to the +% eqivalent frequency Y (in Hz). +% +% See also IOSR.AUDITORY.HZ2ERBRATE. + +% Copyright 2016 University of Surrey. + + y=(10.^(x/21.4)-1)/4.37e-3; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/freqMulti.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/freqMulti.m new file mode 100644 index 0000000000000000000000000000000000000000..2f0312ebc44c91361cadcec790e3bf354c1b2a87 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/freqMulti.m @@ -0,0 +1,24 @@ +function PI = freqMulti(f) +%FREQMULTI Calculate frequency coefficient for ITD-azimuth warping +% +% PI = IOSR.AUDITORY.FREQMULTI(F) calculates the coefficient PI for +% frequency F for use in converting between ITD and azimuth in Kuhn's +% model [1]. +% +% References +% +% [1] Kuhn, G.F. (1977), Model for the interaural time differences in the +% azimuthal plane, The Journal of the Acoustical Society of America +% 62, 1, 157-167. +% +% See also IOSR.AUDITORY.AZIMUTH2ITD, IOSR.AUDITORY.ITD2AZIMUTH. + +% Copyright 2016 University of Surrey. + + PI = zeros(size(f)); + PI(f<=500) = 3; + PI(f>=3000) = 2; + IX = f>500 & f<3000; + PI(IX) = 2.5+0.5.*cos(pi.*((log2((sqrt(6).*f(IX))./1250))./(log2(6)))); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/gammatoneFast.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/gammatoneFast.m new file mode 100644 index 0000000000000000000000000000000000000000..452a977c0418f98da1291424e63e6ac4251e7949 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/gammatoneFast.m @@ -0,0 +1,107 @@ +function [bm,env,delay] = gammatoneFast(x,cfs,fs,align) +%GAMMATONEFAST Produce an array of responses from gammatone filters via FFT +% +% BM = IOSR.AUDITORY.GAMMATONEFAST(X,CFS,FS) passes the vector X through +% a bank of fourth-order gammatone filters, with centre frequencies +% specified by CFS. The function returns a matrix, with each row/column +% corresponding to a filter output with a centre frequency determined by +% the corresponding element in CFS. The orientation of the output is +% determined by the orientation of the input: if X is a row vector then +% the output will contain one row for each filter output, and vice versa. +% +% Centre frequencies may be any value below the Nyquist rate (determined +% by the sampling frequency fs). Typically centre frequencies are equally +% spaced on the ERB-rate scale and may be calculated thus: +% +% CFS = iosr.auditory.makeErbCFs(LOW_CF,HIGH_CF,NUMCHANS) +% +% where LOW_CF is the lowest frequency in the bank, HIGH_CF is the +% highest, and NUMCHANS is the numbers of filters in the bank. +% +% BM = IOSR.AUDITORY.GAMMATONEFAST(...,ALIGN) allows phase alignment to +% be applied. With ALIGN=false, no alignment is applied (default). With +% ALIGN=true, fine structure and envelope alignment is applied so that +% the impulse response peaks occurs at t=0. +% +% [BM,ENV] = IOSR.AUDITORY.GAMMATONEFAST(...) returns the instantaneous +% envelopes ENV for each filter. +% +% [BM,ENV,DELAY] = IOSR.AUDITORY.GAMMATONEFAST(...) returns the delay +% DELAY (in samples) removed by the phase alignment of each gammatone +% filter, i.e. DELAY(n)=0 if ALIGN=true. DELAY is a vector the same size +% as CFS. +% +% Based on code written by ZZ Jin, adapted by DLW in Jan'07 and JF +% Woodruff in Nov'08 +% +% See also IOSR.AUDITORY.MAKEERBCFS. + +% Copyright 2016 University of Surrey. + + if nargin < 3 + fs = 16000; % default sampling frequency + end + if nargin < 4 + align = false; % default phase alignment + end + + % check inputs + assert(isvector(x) & isnumeric(x), 'iosr:gammatoneFast:invalidX', 'x must be a vector') + assert(isvector(cfs) & isnumeric(cfs), 'iosr:gammatoneFast:invalidCfs', 'cfs must be a vector') + assert(isscalar(fs), 'iosr:gammatoneFast:invalidFs', 'fs must be a scalar') + assert(islogical(align) & numel(align)==1, 'iosr:gammatoneFast:invalidAlign', 'align must be logical') + + % number of frequency channels + numchans = length(cfs); + + filterOrder = 4; % filter order + gL = 2^nextpow2(0.128*fs); % gammatone filter length at least 128 ms + b = 1.019.*24.7.*(4.37.*cfs./1000+1); % rate of decay or bandwidth + + gt = zeros(gL,numchans); % Initialise IR + tc = zeros(size(cfs)); % Initialise time lead + phase = 0; + + tpt=(2*pi)/fs; + gain=((1.019.*b.*tpt).^filterOrder)./6; % based on integral of impulse + + tmp_t = (0:gL-1)/fs; + + % calculate impulse response + for i = 1:numchans + if align + tc(i) = (filterOrder-1)./(2*pi*b(i)); + phase = -2*pi*cfs(i)*tc(i); + end + gt(:,i) = gain(i)*fs^3*tmp_t.^(filterOrder-1).*exp(-2*pi*b(i)*tmp_t).*cos(2*pi*cfs(i)*tmp_t+phase); + end + + % if input is row vector, transpose to column vector + rot = false; + if size(x,1)==1 + x = x'; + rot = true; + end + + % gammatone filtering using FFTFILT + bm = fftfilt(gt,repmat(x,1,numchans)); + + % Hilbert envelope + env = abs(hilbert(bm)); + + % delay due to time lead + delay = round(tc.*fs); + + % remove time lead + for i = 1:numchans + bm(:,i) = [bm(delay(i)+1:end,i); zeros(delay(i),1)]; + env(:,i) = [env(delay(i)+1:end,i); zeros(delay(i),1)]; + end + + % transpose output if necessary + if rot + bm = bm'; + env = env'; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/hz2erbRate.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/hz2erbRate.m new file mode 100644 index 0000000000000000000000000000000000000000..5223ffa7e293e1b27526b01c183f4bfdee431c5e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/hz2erbRate.m @@ -0,0 +1,13 @@ +function y=hz2erbRate(x) +%HZ2ERBRATE Convert Hz to ERB rate +% +% Y = IOSR.AUDITORY.HZ2ERBRATE(X) converts the frequency X (in Hz) to the +% eqivalent ERB number Y. +% +% See also IOSR.AUDITORY.ERBRATE2HZ, IOSR.AUDITORY.MAKEERBCFS. + +% Copyright 2016 University of Surrey. + + y=(21.4*log10(4.37e-3*x+1)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/iso226.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/iso226.m new file mode 100644 index 0000000000000000000000000000000000000000..f028332b44578ea66e50f1debb3b203cfa963b21 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/iso226.m @@ -0,0 +1,176 @@ +function [spl, f, params] = iso226(phon,fq,sq) +%ISO226 ISO 226:2003 Normal equal-loudness-level contours +% +% [SPL,F] = IOSR.AUDITORY.ISO226(PHON) returns the sound pressure level +% (SPL) (dB) of pure tone frequencies F (Hz) at the loudness level(s) +% PHON. The values are calculated according to ISO 226:2003 using the +% reference frequencies specified in the standard. According to the +% standard, PHON is only valid at all frequencies if 20<=PHON<80 +% (although the function will return SPL values outside of this range). +% If PHON is 0, the threshold of hearing is returned. +% +% PHON may be an array of any size; SPL and F will be of size +% [1,29,M,N,P,...] where M,N,P,... are the dimensions of PHON. +% +% [SPL,F] = IOSR.AUDITORY.ISO226(PHON,FQ) returns the SPL of the pure +% tone frequencies in FQ at the specified loudness level(s). For +% non-standard frequencies, the SPL is calculated by interpolating the +% parameters used in its calculation. According to the standard, FQ is +% only valid between 20 Hz and 12.5 kHz; the function will extrapolate +% SPL values above 12.5 kHz by mirroring 20 Hz values at 20 kHz. +% +% FQ may be an array of any size; SPL and F will be of size +% [Q,R,S,...,M,N,P,...] where Q,R,S,... are the dimensions of FQ. +% +% ... = IOSR.AUDITORY.ISO226(PHON,FQ,SQ) specifies whether singleton +% dimensions will be removed from the output. With sq=false, singleton +% dimensions will be retained (default), else they will be removed. +% +% ... = IOSR.AUDITORY.ISO226(PHON,[],SQ) uses the standard reference +% frequencies for SPL calculations. +% +% [SPL,F,PARAMS] = IOSR.AUDITORY.ISO226(...) returns the reference +% parameters used to calculate the normal equal-loudness-level contours. +% PARAMAS is a structure with the following fields: +% 'f' : the reference frequencies, +% 'alpha_f' : the exponent of loudness perception, +% 'L_U' : magnitude of the linear transfer function normalized +% at 1000 Hz, and +% 'T_f' : the threshold of hearing. +% +% Example +% +% % Plot equal-loudness contours between 20 and 80 phon +% +% % Calculate SPLs +% phons = 20:10:80; +% [spl,f] = iosr.auditory.iso226(phons,[],true); +% +% % plot +% figure; semilogx(f,spl) +% set(gca,'xlim',[min(f(:)) max(f(:))]) +% legend(num2str(phons'),'location','southwest'); +% title('Equal loudness contours for different loudness levels (in phons)') +% xlabel('Frequency [Hz]') +% ylabel('SPL [dB]') +% +% See also IOSR.AUDITORY.LOUDWEIGHT. + +% Copyright 2016 University of Surrey. + + %% Check input + + if any(phon > 80) + warning('iosr:iso226:phonRange','SPL values may not be accurate for loudness levels above 80 phon.') + elseif any(phon(phon~=0) < 20) + warning('iosr:iso226:phonRange','SPL values may not be accurate for loudness levels below 20 phon.') + end + + if nargin>1 + if ~isempty(fq) + if any(fq(:) < 20 | fq(:) > 4000) && any(phon > 90) + warning('iosr:iso226:frequencyRange','ISO 226:2003 is valid for 20?4000 Hz only up to 90 phon. SPL values may be inaccurate.') + elseif any(fq(:) < 5000 | fq(:) > 12500) && any(phon > 80) + warning('iosr:iso226:frequencyRange','ISO 226:2003 is valid for 5000?12500 Hz only up to 80 phon. SPL values may be inaccurate.') + elseif any(fq(:)>12500) + warning('iosr:iso226:frequencyRange','ISO 226:2003 defines loudness levels up to 12.5 kHz. SPL values for frequencies above 12.5 kHz may be inaccurate.') + end + assert(all(fq(:)>=0), 'iosr:iso226:invalidFrequencies', 'Frequencies must be greater than or equal to 0 Hz.') + end + else + fq = []; + end + + if nargin<3 + sq = false; + else + assert(islogical(sq), 'iosr:iso226:invalidSq', 'sq must be logical.') + end + + %% References + + % reference frequencies + params.f = [20 25 31.5 40 50 63 80 100 125 160 200 250 315 400 ... + 500 630 800 1000 1250 1600 2000 2500 3150 4000 5000 ... + 6300 8000 10000 12500]; + + % exponent of loudness perception + params.alpha_f = [0.532 0.506 0.480 0.455 0.432 0.409 0.387 ... + 0.367 0.349 0.330 0.315 0.301 0.288 0.276 0.267 0.259... + 0.253 0.250 0.246 0.244 0.243 0.243 0.243 0.242 0.242... + 0.245 0.254 0.271 0.301]; + + % magnitude of linear transfer function normalized at 1 kHz + params.L_U = [-31.6 -27.2 -23.0 -19.1 -15.9 -13.0 -10.3 -8.1 ... + -6.2 -4.5 -3.1 -2.0 -1.1 -0.4 0.0 0.3 0.5 0.0 -2.7 ... + -4.1 -1.0 1.7 2.5 1.2 -2.1 -7.1 -11.2 -10.7 -3.1]; + + % threshold of hearing + params.T_f = [78.5 68.7 59.5 51.1 44.0 37.5 31.5 26.5 22.1 17.9... + 14.4 11.4 8.6 6.2 4.4 3.0 2.2 2.4 3.5 1.7 -1.3 -4.2... + -6.0 -5.4 -1.5 6.0 12.6 13.9 12.3]; + + %% Calculate + + % determine frequency range + if isempty(fq) + f = params.f; + else + f = fq; + end + + % output size + out_dims = [size(f) size(phon)]; + + % independent outputs + f_squeeze = zeros(numel(f),numel(phon)); + spl_squeeze = zeros(numel(f),numel(phon)); + + % iterate through phons + for p = 1:numel(phon) + % frequencies for phon level + f_squeeze(:,p) = f(:); + % interpolate reference parameters + if nargin>1 + if any(f_squeeze(:,p) > 12500) + % extrapolate - mirror 20Hz behaviour at 20kHz + f_r_extrap = [params.f 20000]; + alpha_f_r_extrap = [params.alpha_f params.alpha_f(1)]; + L_U_r_extrap = [params.L_U params.L_U(1)]; + T_f_r_extrap = [params.T_f params.T_f(1)]; + else + f_r_extrap = params.f; + alpha_f_r_extrap = params.alpha_f; + L_U_r_extrap = params.L_U; + T_f_r_extrap = params.T_f; + end + % interpolate parameters + alpha_f = interp1(f_r_extrap, alpha_f_r_extrap, f_squeeze(:,p)', 'spline', 'extrap'); + L_U = interp1(f_r_extrap, L_U_r_extrap, f_squeeze(:,p)', 'spline', 'extrap'); + T_f = interp1(f_r_extrap, T_f_r_extrap, f_squeeze(:,p)', 'spline', 'extrap'); + else + alpha_f = params.alpha_f; + L_U = params.L_U; + T_f = params.T_f; + end + % calculate SPL + A_f = 0.00447 * ((10^(0.025*phon(p)))-1.15) + ... + ((0.4*(10.^(((T_f+L_U)./10)-9))).^alpha_f); + if phon(p) > 0 + spl_squeeze(:,p) = ((10./alpha_f).*log10(A_f)) - L_U + 94; + else + spl_squeeze(:,p) = T_f; + end + end + + % reshape outputs + f = reshape(f_squeeze,out_dims); + spl = reshape(spl_squeeze,out_dims); + + % remove singleton dimensions if requested + if sq + f = squeeze(f); + spl = squeeze(spl); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/itd2azimuth.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/itd2azimuth.m new file mode 100644 index 0000000000000000000000000000000000000000..7f9bb6b7d597572c346fcce46d53675991d6c143 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/itd2azimuth.m @@ -0,0 +1,31 @@ +function azimuth = itd2azimuth(itd,f) +%ITD2AZIMUTH Convert ITD to azimuth +% +% AZIMUTH = IOSR.AUDITORY.ITD2AZIMUTH(ITD,F) converts the interaural time +% difference ITD (in seconds) at frequency F (in Hz) to AZIMUTH (in +% degrees) according to Kuhn's model [1]. +% +% References +% +% [1] Kuhn, G.F. (1977), Model for the interaural time differences in the +% azimuthal plane, The Journal of the Acoustical Society of America +% 62, 1, 157-167. +% +% See also IOSR.AUDITORY.AZIMUTH2ITD, IOSR.AUDITORY.FREQMULTI. + +% Copyright 2016 University of Surrey. + + assert(isnumeric(itd), 'iosr:itd2azimuth:invalidItd', 'ITD must be numeric') + assert((isscalar(f) | isscalar(itd)) | numel(f)==numel(itd),... + 'iosr:itd2azimuth:invalidInputs', ... + 'F or ITD must be a scalar, or F and ITD must be the same size') + + % Check sanity of ITDs + assert(all(itd<=iosr.auditory.azimuth2itd(90,f)),... + 'iosr:itd2azimuth:invalidItd', ... + 'ITDs greater than maximum ITD [=iosr.auditory.azimuth2itd(90,f)] have been specified.') + + czero = 344; + azimuth = asind((itd.*czero)./(iosr.auditory.freqMulti(f).*0.091)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/lindemannInh.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/lindemannInh.m new file mode 100644 index 0000000000000000000000000000000000000000..8a1aa25a04f80842f707f40518ddd77f86bba1dc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/lindemannInh.m @@ -0,0 +1,118 @@ +function [L_l,R_l] = lindemannInh(L,R,fs,c_inh,dim) +%LINDEMANNINH Signal pre-processing for Lindemann's cross-correlation +% +% [L_L,R_L] = IOSR.AUDITORY.LINDEMANNINH(L,R,FS) pre-processes left L and +% right R signals for the cross-correlation function based on Lindemann's +% precedence model [1,2]. A crucial parameter for Lindemann's model is +% the "operating point", which controls the amount of inhibition. The +% parameter is actually a function of the input related to its RMS level. +% After half-wave rectifying and filtering the input signals L and R +% (sampled at FS Hz) along the first non-singleton dimension, this +% function applies a gain related to the inhibition parameter C_INH +% (default is 0.3). The gain is identical for all rows, columns, etc. +% Lastly, values outside of the interval [0,1] are not permitted in +% Lindemann's model and hence these values are clipped. +% +% [L_L,R_L] = IOSR.AUDITORY.LINDEMANNINH(L,R,FS,C_INH) uses the specified +% inhibition parameter C_INH. The value must be in the interval [0,1]. +% +% [L_L,R_L] = IOSR.AUDITORY.LINDEMANNINH(L,R,FS,C_INH,DIM) pre-processes +% L and R along the dimension DIM. +% +% References +% +% [1] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. I. Simulation of lateralization +% for stationary signals, The Journal of the Acoustical Society of +% America 80, 6, 1608-1622. +% +% [2] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. II. The law of the first wave +% front, The Journal of the Acoustical Society of America 80, 6, +% 1623-1630. +% +% Further reading +% +% Hummersone, C., Mason, R., Brookes, T. (2013), A comparison of +% computational precedence models for source separation in +% reverberant environments, The Journal of the Audio Engineering +% Society 61, 7/8, 508-520. +% +% See also IOSR.AUDITORY.XCORRLINDEMANN. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(isequal(size(L),size(R)), 'iosr:lindemannInh:invalidInputs', 'L and R arrays must be the same size') + assert(isscalar(fs), 'iosr:lindemannInh:invalidFs', 'FS must be a scalar') + + % default dim + if nargin<5 + dim = find(size(L)>1,1,'first'); + end + + %% process + + % half-wave rectify + L_l = hwr(L); + R_l = hwr(R); + + % filter + cutofffreq=800; + [b,a] = butter(1,cutofffreq*2/fs); + L_l = filter(b,a,L_l,[],dim); + R_l = filter(b,a,R_l,[],dim); + + % inhibition parameter + if nargin < 4 + c_inh = .3; + else + assert(isscalar(c_inh) & isnumeric(c_inh), 'iosr:lindemannInh:invalidCinh', 'c_inh must be a scalar'); + assert(c_inh>=0 || c_inh<=1, 'iosr:lindemannInh:invalidX', 'c_inh must be in the interval (0,1].') + end + + % gain + c_gamma_L = calc_gamma(L,dim); + c_gamma_R = calc_gamma(R,dim); + c_gamma = max([c_gamma_L(:); c_gamma_R(:)]); + + % apply parameters + L_l = apply_gamma(L_l,c_inh,c_gamma); + R_l = apply_gamma(R_l,c_inh,c_gamma); + + % restrict range + L_l = clip(L_l); + R_l = clip(R_l); + +end + +function y = hwr(x) +%HWR half-wave rectify + + y = max(x,0); + +end + +function gamma = calc_gamma(x,dim) +%CALC_GAMMA calculate the gamma + + gamma = sqrt(2).*iosr.dsp.rms(x,dim); + +end + +function y = apply_gamma(x,c_inh,c_gamma) +%APPLY_GAMMA apply gamma to achieve inhibition parameter + + y = (c_inh/c_gamma).*x; + +end + +function y = clip(x) +%CLIP clip input data to [0,1] interval + + y = x; + y(y<0) = 0; + y(y>1) = 1; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/loudWeight.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/loudWeight.m new file mode 100644 index 0000000000000000000000000000000000000000..51e34d26f702d816ed40bf7f3391a2c73e867808 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/loudWeight.m @@ -0,0 +1,121 @@ +function g = loudWeight(f,phon) +%LOUDWEIGHT Calculate loudness weighting coefficients +% +% G = IOSR.AUDITORY.LOUDWEIGHT(F) returns loudness-weighting linear- +% magnitude coefficients for frequencies F (Hz). The function is based on +% the loudness at 65 phons defined in ISO 226:2003. The coefficients are +% scaled such that the G = 1 when F = 1000. +% +% G = IOSR.AUDITORY.LOUDWEIGHT(F,PHON) returns loudness weighting +% coefficients at the loudness level PHON. PHON should be a scalar and, +% according to the standard, is only valid at all frequencies such that +% 20<=PHON<80 (although the function will return extrapolated +% coefficients outside of this range). +% +% The input f may be an array of any size. The outputs will be the same +% size as f, with coefficients calculated for each element. +% +% G = IOSR.AUDITORY.LOUDWEIGHT(F,METHOD) returns loudness weighting +% coefficients for a variety of methods. Specifying METHOD as 'A', 'C', +% or 'Z' selects frequency weighting curves defined in IEC 61672-1:2013; +% 'ISO-226' selects a loudness weighting curve derived from ISO 226:2003 +% at 65 phons; 'B' selects a frequency weighting curve defined in IEC +% 60651:1979; 'D' selects a weighting curve defined in IEC 537:1976. +% +% See also IOSR.AUDITORY.ISO226, IOSR.AUDITORY.DUPWEIGHT. + +% Copyright 2016 University of Surrey. + + %% Check input + + assert(all(f(:)>=0), 'iosr:loudWeight:invalidF', 'f should be greater than or equal to zero!') + + if nargin<2 + phon = 65; + end + + if ischar(phon) + method = phon; + if strcmpi(method,'iso-226') + phon = 65; + end + elseif isnumeric(phon) + method = 'iso-226'; + assert(isscalar(phon), 'iosr:loudWeight:invalidPhon', 'phon must be a scalar.') + else + error('iosr:loudWeight:invalidArg','Second argument should be a scalar or char array.') + end + + %% coefficients + + fr = 1000; + fL = 10^1.5; + fH = 10^3.9; + fA = 10^2.45; + D = sqrt(0.5); + b = (1/(1-D)) * ((fr^2) + (((fL^2)*(fH^2))/(fr^2)) - (D*((fL^2)+(fH^2)))); + c = (fL^2)*(fH^2); + f1 = sqrt((-b - sqrt((b^2) - (4*c))) / (2)); + f4 = sqrt((-b + sqrt((b^2) - (4*c))) / (2)); + f2 = ((3 - sqrt(5)) / 2) * fA; + f3 = ((3 + sqrt(5)) / 2) * fA; + + %% Calculate weighting coefficients + + switch lower(method) + case 'a' + g = a_weighting(f); + case 'b' + g = b_weighting(f); + case 'c' + g = c_weighting(f); + case 'd' + g = d_weighting(f); + case 'z' + g = z_weighting(f); + case 'iso-226' + % calculate weighting coefficients + gdB = iosr.auditory.iso226(phon, 1000) - ... + squeeze(iosr.auditory.iso226(phon, f)); + g = 10.^(gdB./20); + otherwise + error('iosr:loudWeight:unknownMethod','Unknown method.') + end + + function w = a_weighting(f) + %A_WEIGHTING return A-weighting magnitude coefficients + function w = calculate(f) + w = ((f4^2).*(f.^4))./... + ( ((f.^2)+(f1^2)) .* sqrt((f.^2)+(f2^2)) .* sqrt((f.^2)+(f3^2)) .* ((f.^2)+(f4^2)) ); + end + w = calculate(f)./calculate(1000); + end + + function w = b_weighting(f) + %B_WEIGHTING return B-weighting magnitude coefficients + w = ((12200^2).*(f.^3))./... + (((f.^2)+(20.6^2)).*sqrt((f.^2)+(158.5^2)).*((f.^2)+(12200^2))); + end + + function w = c_weighting(f) + %C_WEIGHTING return C-weighting magnitude coefficients + function w = calculate(f) + w = ((f4^2).*(f.^2)) ./... + ( ((f.^2)+(f1^2)) .* ((f.^2)+(f4^2)) ); + end + w = calculate(f)./calculate(1000); + end + + function w = d_weighting(f) + %D_WEIGHTING return D-weighting magnitude coefficients + hf = (((1037918.48-(f.^2)).^2)+(1080768.16.*(f.^2)))./... + (((9837328-(f.^2)).^2)+(11723776.*(f.^2))); + w = (f./(6.8966888496476*(10^(-5)))).*sqrt(hf./(((f.^2)+79919.29).*((f.^2)+1345600))); + end + + function w = z_weighting(f) + %Z_WEIGHTING return Z-weighting magnitude coefficients + w = ones(size(f)); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/makeErbCFs.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/makeErbCFs.m new file mode 100644 index 0000000000000000000000000000000000000000..e5d35e48238fa2e150cd3646cfc5a144969551e2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/makeErbCFs.m @@ -0,0 +1,21 @@ +function cfs = makeErbCFs(mincf,maxcf,numchans) +%MAKEERBCFS Make a series of center frequencies equally spaced in ERB-rate. +% +% This function makes a vector of center frequenies equally spaced on the +% ERB-rate scale. +% +% CFS = IOSR.AUDITORY.MAKEERBCFS(MINCF,MAXCF,NUMCHANS) creates NUMCHANS +% centre frequencies between MINCF and MAXCF. +% +% Adapted from code written by: Guy Brown, University of Sheffield, and +% Martin Cooke. +% +% See also IOSR.AUDITORY.ERBRATE2HZ, IOSR.AUDITORY.HZ2ERBRATE. + +% Copyright 2016 University of Surrey. + + cfs = iosr.auditory.erbRate2hz(... + linspace(iosr.auditory.hz2erbRate(mincf),... + iosr.auditory.hz2erbRate(maxcf),numchans)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/meddisHairCell.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/meddisHairCell.m new file mode 100644 index 0000000000000000000000000000000000000000..5f776f8199fe071d64e0f5d7f5ea67498e893f68 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/meddisHairCell.m @@ -0,0 +1,76 @@ +function y = meddisHairCell(data,sampleRate,subtractSpont) +% Calculate Ray Meddis' hair cell model for a number of channels. +% +% y = iosr.auditory.meddisHairCell(data,sampleRate) +% +% This function calculates Ray Meddis' hair cell model for a +% number of channels. Data is arrayed as one channel per +% row. All channels are done in parallel (but each time step +% is sequential) so it will be much more efficient to +% process lots of channels at once. +% +% (c) 1998 Interval Research Corporation +% 12/11/98: Changed h and added comment at suggestion of +% Alain de Cheveigne + +if (nargin<3), subtractSpont=0; end + +% Parameters from Meddis' April 1990 JASA paper. +M = 1; +A = 5; +B = 300; +g = 2000; +y = 5.05; +l = 2500; +r = 6580; +x = 66.31; +h = 50000; % This parameter scales the discharge rate. Adjust as necessary. + % In combination with the gammatone filterbank (ERBFilterBank), + % h=50000 will produce a steady-state average discharge + % probability of about 135 spikes/s within the 1kHz channel, + % for an input consisting of a 1 kHz sinewave at 60 dB SPL + % (0 dB SPL corresponds to an RMS level of 1.0 at the + % input of the gammatone filter). Scaling and constant + % courtesy of Alain de Cheveigne' + + +% Internal constants +dt = 1/sampleRate; +gdt = g*dt; +ydt = y*dt; +ldt = l*dt; +rdt = r*dt; +xdt = x*dt; +[numChannels, dataLength] = size(data); + +% Initial values +kt = g*A/(A+B); +spont = M*y*kt/(l*kt+y*(l+r)); +c = spont * ones(numChannels,1); +q = c*(l+r)/kt; +w = c*r/x; +zeroVector = zeros(numChannels,1); + +% Now iterate through each time slice of the data. Use the +% max function to implement the "if (0>" test. +y = zeros(numChannels, dataLength); +for i = 1:dataLength + limitedSt = max(data(:,i)+A,0); + kt = gdt*limitedSt./(limitedSt+B); + replenish = max(ydt*(M-q),zeroVector); + eject = kt.*q; + loss = ldt.*c; + reuptake = rdt.*c; + reprocess = xdt.*w; + + q = q + replenish - eject + reprocess; + c = c + eject - loss - reuptake; + w = w + reuptake - reprocess; + y(:,i) = c; +end + +y = h .* y; + +if (subtractSpont > 0) + y=max(0,y-spont); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/perceptualCentroid.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/perceptualCentroid.m new file mode 100644 index 0000000000000000000000000000000000000000..40bcd81ee29acd4d1339d15aed4bfe067e7b7792 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/perceptualCentroid.m @@ -0,0 +1,326 @@ +function [PCmean,PCstd,PCmax,PCmin,N] = perceptualCentroid(x,fs,varargin) +%PERCEPTUALCENTROID Perceptual spectral centroid +% +% PCMEAN = IOSR.AUDITORY.PERCEPTUALCENTROID(X,FS) calculates the spectral +% centroid of signal X, sampled at FS, with respect to mel-frequency. +% +% The algorithm first calculates the spectrogram of X; each segment has +% the maximum of length(X)/8 or 2048 samples, calculated with 50% overlap +% and windowed with a hamming window. The spectrogram function is the +% built-in Matlab function SPECTROGRAM. The centroid is calculated with +% respect to mels by converting the FFT bin frequencies to mels. PCMEAN +% is the mean of the perceptual spectral centroids calculated for each +% segment. The perceptual spectral centroid can also be calculated using +% ERBs, cents, or hertz (see below). +% +% X can be a vector, matrix, or multidimensional array; +% PERCEPTUALCENTROID will operate along the first non-signleton +% dimension, and return a value for each corresponding row/column/etc. +% +% PCMEAN = IOSR.AUDITORY.PERCEPTUALCENTROID(X,FS,'PARAMETER',VALUE) +% allows numerous parameters to be specified. These parameters are:- +% 'cref' : {27.5} | scalar +% Specifies the reference frequency when calulating the centroid +% in terms of cents. +% 'dim' : {first non-singleton dimension} | integer +% Specify the dimension over which to calculate the perceptual +% spectral centroid. +% 'loudness' : {'none'} | 'A' | 'B' | 'C' | 'D' | 'ISO-226' +% Specifies whether loudness weighting is applied to the spectrum +% prior to the centroid calculation. The default is for no +% weighting to be applied. 'A', 'B', 'C', and 'D' correspond to +% frequency weighting curves defined in IEC 61672:2003; 'ISO-226' +% applies loudness weighting derived from ISO 226:2003. +% 'nfft' : {max([length(x)/2, 2048])} | integer +% Specifies SPECTROGRAM's FFT size. +% 'noverlap' : {nfft/2} | integer +% Specifies the number of samples over which SPECTROGRAM's +% segments overlap. +% 'output' : {'units'} | 'hz' +% Specifies whether the output data are in Hz ('hz') or in units +% determined by the 'scale' option ('units') (default). +% 'phon' : {65} | scalar +% Specifies the loudness level if using ISO 226:2003-based +% loudness weighting. +% 'scale' : {'mel'} | 'linear' | 'erb' | 'cents' +% Specifies frequency scale use to calculate the centroid. 'mel' +% uses the mel-frequency scale, 'linear' uses a linear frequency +% scale (corresponding to the traditional spectral centroid +% measure), 'erb' uses the equivalent-rectangular-bandwidth-rate +% scale, and cents uses a scale based on musical cents with +% respect to A-1 (27.5 Hz). +% 'window' : {hamming(nfft)} | vector +% Specifies the window applied to each SPECTROGRAM segment. +% +% [PCMEAN,PCSTD,PCMAX,PCMIN,N] = ... returns additional information:- +% PCMEAN : as described above. +% PCSTD : the standard deviation of the perceptual spectral +% centroids. +% PCMAX : the maximum of the perceptual spectral centroids. +% PCMIN : the minimum of the perceptual spectral centroids. +% N : the sample size for each statistic. +% +% For more information about the FFT calculation and its options, consult +% the SPECTROGRAM documentation. +% +% Examples +% +% Example 1: Calculate the mel-frequency spectral centroid of random +% noise: +% +% fs = 44100; +% x = randn(fs,1); +% PC = iosr.auditory.perceptualCentroid(x,fs); +% +% Example 2: Calculate the ERB-spaced spectral centroid of random +% noise with the output in Hertz: +% +% PC = iosr.auditory.perceptualCentroid(x,fs,... +% 'scale','erb','output','hz'); +% +% Example 3: Calculate the musically-spaced spectral centroid of +% random noise using a 4096-point Hann window: +% +% PC = iosr.auditory.perceptualCentroid(x,fs,... +% 'scale','cents','window',hann(4096)); +% +% Authors: Chris Hummersone & Kirsten Hermes, 2014 +% +% See also SPECTROGRAM. + +% Copyright 2016 University of Surrey. + + %% read inputs and make default assignments + + assert(~isscalar(x), 'iosr:perceptualCentroid:invalidX', '''X'' cannot be a scalar') + + dims = size(x); + + propNames = {'dim','nfft','noverlap','window','scale','output','cref','loudness','phon'}; % permitted prop names + + options = struct; + % read parameter/value options + if nargin>2 % if parameters are specified + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:perceptualCentroid:nameValuePairs','PERCEPTUALCENTROID needs propertyName/propertyValue pairs following the x and fs arguments.') + end + % write parameters to options struct + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + if any(strcmpi(pair{1},propNames)) + propName = char(propNames(find(strcmpi(pair{1},propNames),1,'last'))); + options.(propName) = pair{2}; + else + error('iosr:perceptualCentroid:unknownOption',['Unknown option ''' pair{1} '''']); + end + end + end + + % other parameters + dim = getProperty(options,'dim',find(dims>1,1,'first')); + assert(dim>0 && dim<=length(dims) && isscalar(dim) && round(dim)==dim,... + 'iosr:perceptualCentroid:invalidDim', ... + '''dim'' must be greater than zero and less than or equal to the number of dimensions in X.'); + + % determine window and nfft + defWinHandle = @hamming; % default window function + [nfft,nfft_set] = getProperty(options,'nfft',max([2048,floor(size(x,dim)/8)])); + [window,win_set] = getProperty(options,'window',defWinHandle(nfft)); + + if win_set + % window is specified + if isscalar(window) + window = defWinHandle(window); + end + if ~nfft_set + nfft = length(window); + end + if nfft~=length(window) + error('iosr:perceptualCentroid:invalidFFTlength','NFFT must be equal to the window length.') + end + else + % window is not specified + window = defWinHandle(nfft); + end + + % other parameters + noverlap = getProperty(options,'noverlap',floor(nfft/2)); + scale = getProperty(options,'scale','mel'); + output = getProperty(options,'output','units'); + cref = getProperty(options,'cref',27.5); + loudness = getProperty(options,'loudness','none'); + + % tests + assert(noverlap<min([nfft,length(window)]), 'iosr:perceptualCentroid:invalidNoverlap', '''noverlap'' must be less than ''nfft'' and the window length.'); + assert(isscalar(cref) && cref>0, 'iosr:perceptualCentroid:invalidCref', '''cref'' must be greater than 0.'); + + %% permute and rehape x to operate down columns + + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x2 = rearrange(x,order,[dims_shift(1) numel(x)/dims_shift(1)]); + + %% determine functions + + fHandleDoNothing = @(x,~) (x); + + % choose frequency transformation + switch lower(scale) + case 'linear' + fHandleFromF = fHandleDoNothing; + fHandleToF = fHandleDoNothing; + case 'mel' + fHandleFromF = @frequency2mel; + fHandleToF = @mel2frequency; + case 'erb' + fHandleFromF = @frequency2erb; + fHandleToF = @erb2frequency; + case 'cents' + fHandleFromF = @frequency2cents; + fHandleToF = @cents2frequency; + otherwise + error('iosr:perceptualCentroid:unknownScale',['Requested scale ''' scale ''' not recognised. Options are ''linear'', ''mel'', ''erb'', or ''cents''.']); + end + + % warn if cref but scale~=cents + if ~strcmpi(scale,'cents') && ... + any(cell2mat(strfind(lower(varargin(cellfun(@ischar,varargin))),'cref'))) + warning('iosr:perceptualCentroid:cref','Option ''cref'' only affects the output when ''scale'' is set to ''cents''.') + end + + %% calculate centroid and stats + + % pre-allocate outputes + PCmean = zeros(1,size(x2,2)); + PCstd = zeros(1,size(x2,2)); + PCmax = zeros(1,size(x2,2)); + PCmin = zeros(1,size(x2,2)); + N = zeros(1,size(x2,2)); + + % determine output conversion + switch lower(output) + case 'hz' + % use fHandleToF + case 'units' + fHandleToF = fHandleDoNothing; + otherwise + error('iosr:perceptualCentroid:unknownUnits',['Requested output ''' output ''' not recognised. Options are ''hz'', or ''units''.']); + end + + % determine phon, if relevant + switch lower(loudness) + case 'iso-226' + phon = getProperty(options,'phon',65); + otherwise + if isfield(options,'phon') + warning('iosr:perceptualCentroid:phon','''phon'' option has no effect unless using ''ISO-226'' loudness weighting.') + end + end + + % determine loudness weighting + switch lower(loudness) + case 'none' + w_l = @(x) ones(size(x)); + case 'a' + w_l = @(x) iosr.auditory.loudWeight(x,'a'); + case 'b' + w_l = @(x) iosr.auditory.loudWeight(x,'b'); + case 'c' + w_l = @(x) iosr.auditory.loudWeight(x,'c'); + case 'd' + w_l = @(x) iosr.auditory.loudWeight(x,'d'); + case 'iso-226' + w_l = @(x) iosr.auditory.loudWeight(x,phon); + otherwise + error('iosr:perceptualCentroid:unknownLoudness',['Requested loudness weighting ''' loudness ''' not recognised. Options are ''none'', or ''A''.']); + end + + for c = 1:size(x2,2) % across the dim in input + % caluclate spectrogram + [X,f] = spectrogram(x2(:,c),window,noverlap,nfft,fs); + % ignore frequencies greater than Nyquist + IX = f<=fs/2; + f = f(IX); + % convert frequencies + g = fHandleFromF(f,cref); + % calculate magnitude + mag = abs(X(IX,:)); + % calculate loudness weighting + loud = w_l(f); + % pre-allocate temp centroid values + centroid = zeros(1,size(X,2)); + for d = 1:size(X,2) % iterate through spectrogram windows + centroid(d) = fHandleToF(sum((loud.*mag(:,d)).*g)./sum(loud.*mag(:,d)),cref); + end + centroid(isnan(centroid)) = []; % if the original audio has parts of silence, the spectrogram windows contain only zeros which lead to NaN in centroid calculation. These columns are removed. + % calculate stats + PCmean(c) = mean(centroid); + PCstd(c) = std(centroid); + PCmax(c) = max(centroid); + PCmin(c) = min(centroid); + N(c) = size(X,2); + end + + %% inversely permute output back to input dimensions + + PCmean = irearrange(PCmean,order,[1 dims_shift(2:end)]); + PCstd = irearrange(PCstd,order,[1 dims_shift(2:end)]); + PCmax = irearrange(PCmax,order,[1 dims_shift(2:end)]); + PCmin = irearrange(PCmin,order,[1 dims_shift(2:end)]); + N = irearrange(N,order,[1 dims_shift(2:end)]); + +end + +function f = mel2frequency(m,~) +%MEL2FREQUENCY convert mel to frequency + f = 700.*(exp(m./1127)-1); +end + +function m = frequency2mel(f,~) +%FREQUENCY2MEL convert frequency to mel + m = 1127.*log(1+(f./700)); +end + +function f = erb2frequency(b,~) +%ERB2FREQUENCY convert ERB to frequency + f = (10.^(b./21.4)-1)./0.00437; +end + +function b = frequency2erb(f,~) +%FREQUENCY2ERB convert frequency to ERB + b = 21.4.*log10(1+(0.00437.*f)); +end + +function f = cents2frequency(c,cref) +%CENTS2FREQUENCY convert cents to frequency + f = cref.*(2.^(c./1200)-eps); +end + +function c = frequency2cents(f,cref) +%FREQUENCY2CENTS convert frequency to cents + c = 1200.*log2((f./cref)+eps); +end + +function [propValue,isset] = getProperty(options,propName,default) +%GETPROPERTY return property/default value + if isfield(options,propName) + propValue = options.(propName); + isset = true; + else + propValue = default; + isset = false; + end +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/perceptualCentroid2.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/perceptualCentroid2.m new file mode 100644 index 0000000000000000000000000000000000000000..bb9352a71516821afc18914ac5885c83e8ae3e21 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/perceptualCentroid2.m @@ -0,0 +1,275 @@ +function pc = perceptualCentroid2(x,fs,varargin) +%PERCEPTUALCENTROID2 Alternative perceptual spectral centroid +% +% PC = IOSR.AUDITORY.PERCEPTUALCENTROID2(X,FS) calculates the spectral +% centroid of signal X, sampled at FS, with respect to mel-frequency. +% +% The algorithm first calculates the long-term average spectrum (LTAS) of +% X according to IOSR.DSP.LTAS via the short-time Fourier transform +% (STFT). The perceptual centroid is then calculated using the LTAS. This +% is in contrast to IOSR.AUDITORY.PERCEPTUALCENTROID, which calculates +% the perceptual centroid for a series of spectrogram segments, and then +% takes the average (and other statistics). +% +% X can be a vector, matrix, or multidimensional array; +% PERCEPTUALCENTROID2 will operate along the first non-signleton +% dimension, and return a value for each corresponding row/column/etc. +% +% PC = IOSR.AUDITORY.PERCEPTUALCENTROID2(X,FS,'PARAMETER',VALUE) allows +% numerous parameters to be specified. These parameters are:- +% 'cref' : {27.5} | scalar +% Specifies the reference frequency when calulating the centroid +% in terms of cents. +% 'dim' : {first non-singleton dimension} | integer +% Specify the dimension over which to calculate the perceptual +% spectral centroid. +% 'hop' : {512} | integer +% Specifies the hop size of the STFT. +% 'loudness' : {'none'} | 'A' | 'B' | 'C' | 'D' | 'ISO-226' +% Specifies whether loudness weighting is applied to the spectrum +% prior to the centroid calculation. The default is for no +% weighting to be applied. 'A', 'B', 'C', and 'D' correspond to +% frequency weighting curves defined in IEC 61672:2003; 'ISO-226' +% applies loudness weighting derived from ISO 226:2003. +% 'noct' : {12} | scalar +% Apply 1/noct-octave smoothing to the frequency spectrum. +% Setting 'noct' to 0 results in no smoothing. +% 'output' : {'units'} | 'hz' +% Specifies whether the output data are in Hz ('hz') or in units +% determined by the 'scale' option ('units') (default). +% 'phon' : {65} | scalar +% Specifies the loudness level if using ISO 226:2003-based +% loudness weighting. +% 'scale' : {'mel'} | 'linear' | 'erb' | 'cents' +% Specifies frequency scale use to calculate the centroid. 'mel' +% uses the mel-frequency scale, 'linear' uses a linear frequency +% scale (corresponding to the traditional spectral centroid +% measure), 'erb' uses the equivalent-rectangular-bandwidth-rate +% scale, and cents uses a scale based on musical cents with +% respect to A-1 (27.5 Hz). +% 'window' : {hamming(1024)} | vector +% Specifies the window applied to each STFT segment. +% +% Examples +% +% Example 1: Calculate the mel-frequency spectral centroid of random +% noise: +% +% fs = 44100; +% x = randn(fs,1); +% PC = iosr.auditory.perceptualCentroid2(x,fs); +% +% Example 2: Calculate the ERB-spaced spectral centroid of random +% noise with the output in Hertz: +% +% PC = iosr.auditory.perceptualCentroid2(x,fs,... +% 'scale','erb','output','hz'); +% +% Example 3: Calculate the musically-spaced spectral centroid of +% random noise using a 4096-point Hann window: +% +% PC = iosr.auditory.perceptualCentroid2(x,fs,... +% 'scale','cents','window',hann(4096)); +% +% Authors: Chris Hummersone & Kirsten Hermes, 2014 +% +% See also IOSR.DSP.LTAS, IOSR.AUDITORY.PERCEPTUALCENTROID. + +% Copyright 2016 University of Surrey. + + %% read inputs and make default assignments + + assert(~isscalar(x), 'iosr:perceptualCentroid2:invalidX', '''X'' cannot be a scalar') + + dims = size(x); + + propNames = {'dim','hop','noct','window','scale','output','cref','loudness','phon'}; % permitted prop names + + options = struct; + % read parameter/value options + if nargin>2 % if parameters are specified + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:perceptualCentroid2:nameValuePairs','PERCEPTUALCENTROID2 needs propertyName/propertyValue pairs following the x and fs arguments.') + end + % write parameters to options struct + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + if any(strcmpi(pair{1},propNames)) + propName = char(propNames(find(strcmpi(pair{1},propNames),1,'last'))); + options.(propName) = pair{2}; + else + error('iosr:perceptualCentroid2:unknownOption',['Unknown option ''' pair{1} '''']); + end + end + end + + % other parameters + dim = getProperty(options,'dim',find(dims>1,1,'first')); + assert(dim>0 && dim<=length(dims) && isscalar(dim) && round(dim)==dim,... + 'iosr:perceptualCentroid2:invalidDim', ... + '''dim'' must be greater than zero and less than or equal to the number of dimensions in X.'); + + % other parameters + window = getProperty(options,'window',hamming(1024)); + hop = getProperty(options,'hop',512); + noct = getProperty(options,'noct',12); + scale = getProperty(options,'scale','mel'); + output = getProperty(options,'output','units'); + cref = getProperty(options,'cref',27.5); + loudness = getProperty(options,'loudness','none'); + + % tests + assert(isscalar(cref) && cref>0, 'iosr:perceptualCentroid2:invalidCref', '''cref'' must be greater than 0.'); + + %% permute and rehape x to operate down columns + + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x2 = rearrange(x,order,[dims_shift(1) numel(x)/dims_shift(1)]); + + %% determine functions + + fHandleDoNothing = @(x,~) (x); + + % choose frequency transformation + switch lower(scale) + case 'linear' + fHandleFromF = fHandleDoNothing; + fHandleToF = fHandleDoNothing; + case 'mel' + fHandleFromF = @frequency2mel; + fHandleToF = @mel2frequency; + case 'erb' + fHandleFromF = @frequency2erb; + fHandleToF = @erb2frequency; + case 'cents' + fHandleFromF = @frequency2cents; + fHandleToF = @cents2frequency; + otherwise + error('iosr:perceptualCentroid2:unknownScale',['Requested scale ''' scale ''' not recognised. Options are ''linear'', ''mel'', ''erb'', or ''cents''.']); + end + + % warn if cref but scale~=cents + if ~strcmpi(scale,'cents') && ... + any(cell2mat(strfind(lower(varargin(cellfun(@ischar,varargin))),'cref'))) + warning('iosr:perceptualCentroid2:cref','Option ''cref'' only affects the output when ''scale'' is set to ''cents''.') + end + + %% calculate centroid and stats + + % pre-allocate outputes + pc = zeros(1,size(x2,2)); + + % determine output conversion + switch lower(output) + case 'hz' + % use fHandleToF + case 'units' + fHandleToF = fHandleDoNothing; + otherwise + error('iosr:perceptualCentroid2:unknownUnits',['Requested output ''' output ''' not recognised. Options are ''hz'', or ''units''.']); + end + + % determine phon, if relevant + switch lower(loudness) + case 'iso-226' + phon = getProperty(options,'phon',65); + otherwise + if isfield(options,'phon') + warning('iosr:perceptualCentroid2:phon','''phon'' option has no effect unless using ''ISO-226'' loudness weighting.') + end + end + + % determine loudness weighting + switch lower(loudness) + case 'none' + w_l = @(x) ones(size(x)); + case 'a' + w_l = @(x) iosr.auditory.loudWeight(x,'a'); + case 'b' + w_l = @(x) iosr.auditory.loudWeight(x,'b'); + case 'c' + w_l = @(x) iosr.auditory.loudWeight(x,'c'); + case 'd' + w_l = @(x) iosr.auditory.loudWeight(x,'d'); + case 'iso-226' + w_l = @(x) iosr.auditory.loudWeight(x,phon); + otherwise + error('iosr:perceptualCentroid2:unknownLoudness',['Requested loudness weighting ''' loudness ''' not recognised. Options are ''none'', or ''A''.']); + end + + for c = 1:size(x2,2) % across the dim in input + % caluclate spectrogram + [X,f] = iosr.dsp.ltas(x2(:,c),fs,'win',window,'hop',hop,'noct',noct,'units','none'); + % ignore frequencies greater than Nyquist + IX = f<=fs/2; + f = f(IX); + % convert frequencies + g = fHandleFromF(f,cref); + % calculate magnitude + mag = sqrt(X(IX,:)); + % calculate loudness weighting + loud = w_l(f); + % calculate centroid + pc(c) = fHandleToF(sum((loud.*mag).*g)./sum(loud.*mag),cref); + end + + %% inversely permute output back to input dimensions + + pc = irearrange(pc,order,[1 dims_shift(2:end)]); + +end + +function f = mel2frequency(m,~) +%MEL2FREQUENCY convert mel to frequency + f = 700.*(exp(m./1127)-1); +end + +function m = frequency2mel(f,~) +%FREQUENCY2MEL convert frequency to mel + m = 1127.*log(1+(f./700)); +end + +function f = erb2frequency(b,~) +%ERB2FREQUENCY convert ERB to frequency + f = (10.^(b./21.4)-1)./0.00437; +end + +function b = frequency2erb(f,~) +%FREQUENCY2ERB convert frequency to ERB + b = 21.4.*log10(1+(0.00437.*f)); +end + +function f = cents2frequency(c,cref) +%CENTS2FREQUENCY convert cents to frequency + f = cref.*(2.^(c./1200)-eps); +end + +function c = frequency2cents(f,cref) +%FREQUENCY2CENTS convert frequency to cents + c = 1200.*log2((f./cref)+eps); +end + +function [propValue,isset] = getProperty(options,propName,default) +%GETPROPERTY return property/default value + if isfield(options,propName) + propValue = options.(propName); + isset = true; + else + propValue = default; + isset = false; + end +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/xcorrLindemann.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/xcorrLindemann.m new file mode 100644 index 0000000000000000000000000000000000000000..5745c9986ddea2c6223a50af4730dc6dc47b0cb3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/xcorrLindemann.m @@ -0,0 +1,110 @@ +function [c,lags] = xcorrLindemann(L,R,fs,maxlag,dim) +%XCORRLINDEMANN Cross-correlation based on Lindemann's precedence model +% +% C = IOSR.AUDITORY.XCORRLINDEMANN(L,R,FS) calculates the +% cross-correlation of vectors L and R, sampled at FS Hz, using a maximum +% cross-correlation lag of 0.001*fs samples (1 ms). The cross-correlation +% function is based on Lindemann's [1,2] precedence model. C is the same +% size as L or R, except that size(C,1) = 2*0.001*fs+1. +% +% C = IOSR.AUDITORY.XCORRLINDEMANN(L,R,FS,MAXLAG) calculates the +% cross-correlation using a maximum cross-correlation lag of MAXLAG +% samples. +% +% C = IOSR.AUDITORY.XCORRLINDEMANN(L,R,FS,MAXLAG,DIM) performs the +% cross-correlation along the dimension DIM. C is the same size as L or +% R, except that size(C,DIM) = 2*MAXLAG+1. +% +% [C,LAGS] = IOSR.AUDITORY.XCORRLINDEMANN(...) returns the lags, in +% seconds, over which the cross-correlation was calculated. +% +% References +% +% [1] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. I. Simulation of lateralization +% for stationary signals, The Journal of the Acoustical Society of +% America 80, 6, 1608-1622. +% +% [2] Lindemann, W. (1986), Extension of a binaural cross-correlation +% model by contralateral inhibition. II. The law of the first wave +% front, The Journal of the Acoustical Society of America 80, 6, +% 1623-1630. +% +% See also IOSR.AUDITORY.LINDEMANNINH, XCORR. + +% Copyright 2016 University of Surrey. + + %% check input + assert(isequal(size(L),size(R)), 'iosr:xcorrLindemann:invalidSignals', 'L and R must be the same size'); + assert(isscalar(fs) & isnumeric(fs), 'iosr:xcorrLindemann:invalidFs', 'FS must be a scalar'); + + % check for maxlag + if nargin<4 + maxlag = 0.001*fs; + else + assert(isscalar(maxlag) & isnumeric(maxlag), 'iosr:xcorrLindemann:invalidMaxlag', 'MAXLAG must be a scalar'); + end + + % check for dim + dims = size(L); + if nargin<5 + dim = find(dims>1,1,'first'); + else + assert(isscalar(dim) && round(dim)==dim, 'iosr:xcorrLindemann:invalidDim', 'DIM must be an integer scalar') + end + + % check L and R have a valid range + if any(L(:)<0) || any(R(:)<0) || any(L(:)>1) || any(R(:)>1) + error('iosr:xcorrLindemann:inputOutOfRange','L and/or R contain values outside of the range [0,1]. This is not allowed. Use LINDEMANN_INH to pre-process the L and R inputs.') + end + + % check C function is compiled + iosr.general.checkMexCompiled('-largeArrayDims',fullfile(fileparts(mfilename('fullpath')),'xcorrLindemann_c.c')) + + %% re-arrange input + + % re-arrange array to operate along columns + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + L = rearrange(L,order,[dims_shift(1),numel(L)/dims_shift(1)]); + R = rearrange(R,order,[dims_shift(1),numel(R)/dims_shift(1)]); + + %% do cross-correlation + + % time constants + t_int = 5; % ms + t_inh = 10; % ms + + xcorr_length = round(2*maxlag)+1; % length of cross-correlation + c = zeros(xcorr_length,size(L,2)); % pre-allocate + for n = 1:size(L,2) + c(:,n) = iosr.auditory.xcorrLindemann_c(L(:,n),R(:,n),fs,maxlag,t_inh,t_int); + end + + %% return values + + % rearrange to match input dimensions + c = irearrange(c,order,[xcorr_length dims_shift(2:end)]); + + % return lags + if nargin>1 + lags = (-maxlag:maxlag)./fs; + end + +end + +function y = rearrange(x,dim_order,shape) +%REARRANGE rearrange data to 2-D matrix with target dim as column + + y = permute(x,dim_order); + y = reshape(y,shape); + +end + +function y = irearrange(x,dim_order,shape) +%IREARRANGE inverse rearrangement + + y = reshape(x,shape); + y = ipermute(y,dim_order); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/xcorrLindemann_c.c b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/xcorrLindemann_c.c new file mode 100644 index 0000000000000000000000000000000000000000..a215c98e93ba3ca55e8722f9bc4cdd899641af21 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+auditory/xcorrLindemann_c.c @@ -0,0 +1,143 @@ +/* Lindemann's precedence model. + * + * Copyright 2016 University of Surrey. + * + */ + +#include "math.h" +#include "mex.h" + +#define TEMP_ARRAY mxCreateDoubleMatrix((mwSize)length_c,(mwSize)1,mxREAL) +#define IN_ARRAY mxCreateDoubleMatrix((mwSize)n_sample,(mwSize)1,mxREAL) + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + /* ====================== INPUTS & SCALARS ====================== */ + + double *L = mxGetPr(prhs[0]), /* pointer to left signal input */ + *R = mxGetPr(prhs[1]), /* pointer to right signal input */ + fs = *mxGetPr(prhs[2]); /* samle frequency */ + + mwSize maxlag = *mxGetPr(prhs[3]); /* maximum lag */ + + double tinh = (*mxGetPr(prhs[4]))/1000.0, /* fade-off time constant */ + tint = (*mxGetPr(prhs[5]))/1000.0, /* integration time constant */ + td = 0.5*(1.0/fs), /* half sample period */ + alpha = exp(-td/tinh), /* fade-off factor */ + alpha2 = exp(-td/tint), /* integration factor */ + Mf = 6.0, /* fading constant for monaural sensitivity */ + wf = 0.035; /* monaural sensitivity of a correlator to the signal at the end of a delay line */ + + /* sizes */ + mwSize numsamples = mxGetM(prhs[0]), /* number of samples */ + length_c = (2*maxlag)+1, /* length of cross-correlation (2*maxlag)+1 */ + in_length = length_c+numsamples-1, /* length of input to cross-correlation */ + n_sample = 2*in_length-1; /* length of inhibited input to cross-correlation */; + + /* indices */ + mwIndex n, /* sample */ + m, /* lag */ + leftn, /* left samples to be cross-correlated */ + rightn; /* right samples to be cross-correlated */ + + /* ====================== TEMP ARRAYS ====================== */ + + /* monaural sensitivity functions */ + mxArray *wl_mx,*wr_mx; + wl_mx = TEMP_ARRAY; + wr_mx = TEMP_ARRAY; + double *wl = mxGetPr(wl_mx), + *wr = mxGetPr(wr_mx); + for ( m = 0; m < length_c; m++ ) { + wl[m] = wf*exp(-((double)m)/Mf); + wr[m] = wf*exp(((double)m-(double)length_c+1.0)/Mf); + } + + /* running cross-correlation */ + mxArray *k_mx; + k_mx = TEMP_ARRAY; + double *k = mxGetPr(k_mx); + + /* inhibited input to the cross-correlation */ + mxArray *lc_mx,*rc_mx; + lc_mx = TEMP_ARRAY; + rc_mx = TEMP_ARRAY; + double *lc = mxGetPr(lc_mx), + *rc = mxGetPr(rc_mx); + + /* input to cross-correlation */ + mxArray *lin_mx,*rin_mx; + lin_mx = IN_ARRAY; + rin_mx = IN_ARRAY; + double *lin = mxGetPr(lin_mx), + *rin = mxGetPr(rin_mx); + + /* inhibitory components */ + mxArray *il_mx,*ir_mx; + il_mx = TEMP_ARRAY; + ir_mx = TEMP_ARRAY; + double *il = mxGetPr(il_mx), + *ir = mxGetPr(ir_mx); + + /* dynamic inhibitory component for current and previous samples */ + mxArray *phin_mx,*phic_mx; + phin_mx = TEMP_ARRAY; + phic_mx = TEMP_ARRAY; + double *phin = mxGetPr(phin_mx), + *phic = mxGetPr(phic_mx); + + /* inhibited cross-correlation for current and previous samples */ + mxArray *sumn_mx,*sumc_mx; + sumn_mx = TEMP_ARRAY; + sumc_mx = TEMP_ARRAY; + double *sumn = mxGetPr(sumn_mx), + *sumc = mxGetPr(sumc_mx); + + /* ====================== OUTPUT ====================== */ + + plhs[0] = TEMP_ARRAY; + double *c_out = mxGetPr(plhs[0]); + + /* ====================== CROSS-CORRELATE ====================== */ + + for ( n = 0 ; n < numsamples ; n++ ) { + /* input to cross-correlation */ + lin[(2*n)] = L[n]; + rin[(2*n)] = R[n]; + } + for ( n = 0; n < n_sample; n++ ) { + for ( m = 0; m < 2*maxlag; m++ ) { + /* inhibit input to cross-correlation */ + lc[m] = lc[m+1]*il[m+1]; + rc[(2*maxlag)-m] = rc[(2*maxlag)-m-1]*ir[(2*maxlag)-m-1]; + } + lc[length_c-1] = lin[n]; + rc[0] = rin[n]; + /* cross-correlate */ + for ( m = 0; m < length_c; m++ ) { + k[m] = (wl[m]+(1.0-wl[m])*rc[m])*(wr[m]+(1.0-wr[m])*lc[m]); + phin[m] = k[m]+alpha*phic[m]*(1-k[m]); + phic[m]=phin[m]; + il[m]=(1.0-rc[m])*(1-phic[m]); + ir[m]=(1.0-lc[m])*(1-phic[m]); + sumn[m]=sumc[m]*alpha2+(1.0-alpha2)*k[m]; + sumc[m]=sumn[m]; + c_out[m] += sumn[m]; + } + } + /* Destroy mx arrays */ + mxDestroyArray(wl_mx); + mxDestroyArray(wr_mx); + mxDestroyArray(k_mx); + mxDestroyArray(lc_mx); + mxDestroyArray(rc_mx); + mxDestroyArray(il_mx); + mxDestroyArray(ir_mx); + mxDestroyArray(phin_mx); + mxDestroyArray(phic_mx); + mxDestroyArray(sumn_mx); + mxDestroyArray(sumc_mx); + mxDestroyArray(lin_mx); + mxDestroyArray(rin_mx); + return; +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/applyIdealMasks.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/applyIdealMasks.m new file mode 100644 index 0000000000000000000000000000000000000000..0aeee55f51cf3d08e1cadd351e51740199b2d3a5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/applyIdealMasks.m @@ -0,0 +1,116 @@ +function [z_irm,z_ibm,t] = applyIdealMasks(xt,xi,nfft,hop,fs) +%APPLYIDEALMASKS Calculate and apply ideal masks via STFT +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI) calculates the ideal ratio mask +% (IRM) and applies it to the mixture XT+XI, where XT is the target +% signal and XI is the interference signal. The IRM is calculated via the +% STFT using 1024-point windows with 512-point overlap. Z_IRM, XT, and XI +% are vectors. If XT and XI are of different lengths then the shorter +% signal is zero-padded in order to make them the same length; Z_IRM is +% the same length as XT and XI. +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI,NFFT) uses NFFT-length segments +% in the STFT. +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI,WINDOW) uses +% LENGTH(WINDOW)-length segments in the STFT and applies WINDOW to each +% segment. +% +% Z_IRM = IOSR.BSS.APPLYIDEALMASKS(XT,XI,WINDOW,HOP) uses hop size HOP +% for the STFT. +% +% [Z_IRM,Z_IBM] = IOSR.BSS.APPLYIDEALMASKS(...) calculates the ideal +% binary mask (IBM) and applies it to the mixture, returning the result +% to Z_IBM. +% +% [Z_IRM,Z_IBM,T] = IOSR.BSS.APPLYIDEALMASKS(XT,XI,WINDOW,HOP,FS) uses +% sampling frequency FS to return the corresponding time T of each +% element in Z_IRM and Z_IBM. +% +% See also IOSR.DSP.STFT, IOSR.DSP.ISTFT, IOSR.BSS.IDEALMASKS, +% IOSR.BSS.APPLYMASKS. + +% Copyright 2016 University of Surrey. + + %% check input + + % check signals + assert(isvector(xt) && numel(xt)>1, 'iosr:applyIdealMasks:invalidXt', 'XT must be a vector') + assert(isvector(xi) && numel(xi)>1, 'iosr:applyIdealMasks:invalidXi', 'XI must be a vector') + + % make equal length + maxlength = max([length(xi) length(xt)]); + xt = pad(xt,maxlength); + xi = pad(xi,maxlength); + + % check nfft + if nargin<3 + nfft = 1024; + end + + % determine window + if numel(nfft)>1 + win = nfft; + assert(isvector(win), 'iosr:applyIdealMasks:invalidWin', 'WINDOW must be a vector') + nfft = length(win); + else + assert(round(nfft)==nfft && nfft>0, 'iosr:applyIdealMasks:invalidNfft', 'NFFT must be a positive integer') + win = hamming(nfft); + end + + % check x length + assert(length(xt)>=nfft, 'iosr:applyIdealMasks:invalidXt', 'XT must have at least NFFT samples') + assert(length(xi)>=nfft, 'iosr:applyIdealMasks:invalidXi', 'XI must have at least NFFT samples') + + % determine hop + if nargin<4 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:applyIdealMasks:invalidHop', 'HOP must be an integer') + assert(hop<=nfft && hop>0, 'iosr:applyIdealMasks:invalidHop', 'HOP must be less than or equal to NFFT, and greater than 0') + end + + % determine fs + if nargin<5 + fs = 1; + else + assert(isscalar(fs), 'iosr:applyIdealMasks:invalidFs', 'FS must be an scalar') + end + + %% calculate outputs + + % STFTs of signals and mixture + st = iosr.dsp.stft(xt,win,hop); + si = iosr.dsp.stft(xi,win,hop); + mix = iosr.dsp.stft(xt+xi,win,hop); + + % return ideal masks + [irm,ibm] = iosr.bss.idealMasks(st,si); + + % apply IRM + z_irm = iosr.bss.applyMask(mix,irm,nfft,hop,fs); + z_irm = pad(z_irm,maxlength); + + % apply IBM + if nargout>1 + z_ibm = iosr.bss.applyMask(mix,ibm,nfft,hop,fs); + z_ibm = pad(z_ibm,maxlength); + end + + % calculate t + if nargout>2 + t = (0:length(z_irm)-1)./fs; + end + +end + +function y = pad(x,dur) +%PAD Zero-pad a vector + + if length(x)<dur + y = [x(:); zeros(dur-length(x),1)]; + else + y = x(:); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/applyMask.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/applyMask.m new file mode 100644 index 0000000000000000000000000000000000000000..b84cec85ff3d3740afb3a02ef2cb133b50aef811 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/applyMask.m @@ -0,0 +1,64 @@ +function [z,t] = applyMask(s,m,nfft,hop,fs) +%APPLYMASK Apply a time-frequency mask to an STFT +% +% Z = IOSR.BSS.APPLYMASK(S,M) applies the time-frequency mask M to STFT +% S. S has dimensions [N,K] where N is the number of frequency bins and K +% is the number of time frames. The ISTFT is calculated using 1024-point +% FFTs and hop sizes of 512 points. +% +% Z = IOSR.BSS.APPLYMASK(S,M,NFFT) uses NFFT-length segments in the +% ISTFT. +% +% Z = IOSR.BSS.APPLYMASK(S,M,NFFT,HOP) uses hop size HOP for the ISTFT. +% +% [Z,T] = IOSR.BSS.APPLYMASK(S,M,NFFT,HOP,FS) uses sampling frequency FS +% to return the corresponding time T of each element in Z. +% +% See also IOSR.DSP.STFT, IOSR.DSP.ISTFT, IOSR.BSS.IDEALMASKS, +% IOSR.BSS.APPLYIDEALMASKS. + +% Copyright 2016 University of Surrey. + + %% check input + + % check input + if nargin<2 + error('iosr:applyMask:nargin','Not enough input arguments') + end + + % check compulsory inputs + assert(isequal(size(s),size(m)), 'iosr:applyMask:invalidInput', 'S and M must be the same size') + + % check nfft + if nargin<3 + nfft = 1024; + else + assert(isscalar(nfft) && round(nfft)==nfft && nfft>0, 'iosr:applyMask:invalidNfft', 'NFFT must be a positive scalar integer') + end + + % determine hop + if nargin<4 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:applyMask:invalidHop', 'HOP must be an integer') + assert(hop<=nfft && hop>0, 'iosr:applyMask:invalidHop', 'HOP must be less than or equal to NFFT, and greater than 0') + end + + % determine fs + if nargin<5 + fs = 1; + else + assert(isscalar(fs), 'iosr:applyMask:invalidFs', 'FS must be an scalar') + end + + %% calculate outputs + + % apply mask and return signal + z = iosr.dsp.istft(s.*m,nfft,hop); + + % return time + if nargout>1 + t = (0:length(z)-1)./fs; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/calcImr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/calcImr.m new file mode 100644 index 0000000000000000000000000000000000000000..7f88f3f793952507887a9dbbf789e001fecb9f97 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/calcImr.m @@ -0,0 +1,39 @@ +function IMR = calcImr(m,im) +%CALCIMR Calculates the Ideal Mask Ratio (IMR) +% +% IMR = IOSR.BSS.CALCIMR(M,IM) calculates the ideal mask ratio (IMR) from +% the calculated mask M and ideal mask IM. Masks can be logical or +% double, but must only contain values in the interval [0,1]. + +% Copyright 2016 University of Surrey. + + % check input + assert(nargin>1, 'iosr:calcImr:invalidInput', 'You need 2 masks to calculate IMR!') + assert(size(m,1)>1 & size(m,2)>1, 'iosr:calcImr:invalidMask', 'm must be a two-dimensional matrix') + assert(size(im,1)>1 & size(im,2)>1, 'iosr:calcImr:invalidMask', 'im must be a two-dimensional matrix') + assert(all(size(m)==size(im)), 'iosr:calcImr:invalidMask', 'Masks must be the same size!') + + % validate masks + m = check_mask(m); + im = check_mask(im); + + % calculate IMR + lamda = sum(sum(m.*im)); + rho = sum(sum(abs(m-im))); + + IMR = lamda/(lamda+rho); + +end + +function m = check_mask(m) +%CHECK_MASK validate mask + + if ~islogical(m) + if any(m(:)<0) || any(m(:)>1); + error('iosr:calcImr:maskValuesOutOfRange','Values outside of [0,1] were found.') + end + else % make numeric + m = +m; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/calcSnr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/calcSnr.m new file mode 100644 index 0000000000000000000000000000000000000000..ec6bec299d696485f513a4d388da17883ab780eb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/calcSnr.m @@ -0,0 +1,49 @@ +function snr = calcSnr(output,target) +%CALCSNR Calculate the separation SNR +% +% SNR = IOSR.BSS.CALCSNR(OUTPUT,TARGET) calculate the separation +% signal-to-noise ratio in dB for a re-synthesised output compared to the +% ideal target. OUTPUT and TARGET should be vectors of equal length. + +% Copyright 2016 University of Surrey. + + % check input + if ~isvector(output) + error('iosr:calcSnr:invalidOutput','''output'' must be a vector') + end + if ~isvector(target) + error('iosr:calcSnr:invalidTarget','''target'' must be a vector') + end + if numel(output)~=numel(target) + error('iosr:calcSnr:inputLengths','inputs must be the same length') + end + if size(output,1)==1 + output = output'; + end + if size(target,1)==1 + target = target'; + end + + % remove delay caused by convolution + cc = xcorr(output.^2,target.^2); + + delay = find(cc==max(cc))-length(output); + + if delay > 0 + target = [zeros(delay,1); target]; + output = [output; zeros(delay,1)]; + elseif delay < 0 + delay = -delay; + output = [zeros(delay,1); output]; + target = [target; zeros(delay,1)]; + end + + % account for arbitrary gain + if sum(abs(output(:))) > 0 + G = output\target; + output = output.*G; + end + + snr = 10*log10(sum(target.^2)/sum((output-target).^2)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/cfs2fcs.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/cfs2fcs.m new file mode 100644 index 0000000000000000000000000000000000000000..20aaddb624b1df21a65839e24e9d706782123e46 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/cfs2fcs.m @@ -0,0 +1,57 @@ +function fcs = cfs2fcs(cfs,fs) +%CFS2FCS Calculate gammatone crossover frequencies. +% +% FCS = IOSR.BSS.CFS2FCS(CFS,FS) calculates the crossover frequencies of a +% gammatone filterbank. The output fcs is the same size as CFS, with the +% last element being equal to fs/2. +% +% The crossover frequencies are determined empirically by measuring the +% impulse responses of the gammatone filters. +% +% See also IOSR.AUDITORY.GAMMATONEFAST, IOSR.AUDITORY.MAKEERBCFS. + +% Copyright 2016 University of Surrey. + + % Pre-allocate cut-off frequencies + fcs = zeros(size(cfs)); + fcs(end) = fs/2; + + % Create impulse to derive cut-offs empirically + imp_length = fs; + imp = zeros(imp_length,1); + imp(1) = 1; + + % Pre-allocate gammatone transfer functions + if mod(imp_length,2)==0 + z_length = (imp_length/2)+1; + else + z_length = (imp_length+1)/2; + end + gamma_TF = zeros(z_length,length(cfs)); + + % Filter impulses and calculate transfer functions. + for i = 1:length(cfs) + % filter + gamma_imp = iosr.auditory.gammatoneFast(imp,cfs,fs); + % transfer function + temp = abs(fft(gamma_imp)); + gamma_TF(:,i) = temp(1:z_length); + end + + f = ((0:z_length-1)./imp_length).*fs; + + % Find cross point of transfer functions. + for i = 1:length(cfs)-1 + IX = f>cfs(i) & f<cfs(i+1); + if sum(IX)>0 + f_temp = f(IX); + low_TF = gamma_TF(IX,i); + high_TF = gamma_TF(IX,i+1); + diff_TF = abs(high_TF-low_TF); + fcs(i) = f_temp(find(diff_TF==min(diff_TF),1,'first')); + else + fcs(i) = mean([cfs(i) cfs(i+1)]); + end + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/example.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/example.m new file mode 100644 index 0000000000000000000000000000000000000000..a1528e1eb8038c2e1fe3f6cfa98cb3d1705d2462 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/example.m @@ -0,0 +1,94 @@ +%% determine STFT parameters + +hop = 128; +nfft = 1024; +win = hann(nfft); + +%% load signals + +load('handel.mat','y','Fs') +xt = y; +load('laughter.mat','y','Fs') +xi = y; + +% crop xt +xt = xt(1:length(xi)); + +%% calculate and plot STFTs + +% calculate STFTs +[st,f,t] = iosr.dsp.stft(xt,win,hop,Fs); +si = iosr.dsp.stft(xi,win,hop,Fs); + +% calculate spectrograms +stlog = 20.*log10(abs(st)); +silog = 20.*log10(abs(si)); + +% calculate colormap limits +clim = [min([stlog(:); silog(:)]) max([stlog(:); silog(:)])]; + +% draw figures +figure +% +subplot(8,4,[1 2 5 6]) +imagesc(t,f,stlog) +set(gca,'ydir','normal','xticklabel',[],'clim',clim) +title('Target spectrogram') +ylabel('Frequency [Hz]') +ch = colorbar; +ylabel(ch,'Magnitude [dB]') +% +subplot(8,4,[9 10 13 14]) +imagesc(t,f,silog) +set(gca,'ydir','normal','clim',clim) +title('Interference spectrogram') +xlabel('Time [s]') +ylabel('Frequency [Hz]') +ch = colorbar; +ylabel(ch,'Magnitude [dB]') + +%% calculate and plot ideal masks + +% calculate ideal masks +[irm,ibm] = iosr.bss.idealMasks(st,si); + +% draw figures +subplot(8,4,[3 4 7 8]) +imagesc(t,f,irm) +set(gca,'ydir','normal','xticklabel',[],'yticklabel',[],'clim',[0 1]) +title('Ideal ratio mask (IRM)') +ch = colorbar; +ylabel(ch,'Mask value') +% +subplot(8,4,[11 12 15 16]) +imagesc(t,f,ibm) +set(gca,'ydir','normal','yticklabel',[],'clim',[0 1]) +title('Ideal binary mask (IBM)') +xlabel('Time [s]') +ch = colorbar; +ylabel(ch,'Mask value') + +%% resynthesise and plot output + +% calculate and apply ideal masks in one step +[z_irm,z_ibm,t] = iosr.bss.applyIdealMasks(xt,xi,win,hop,Fs); + +% draw figures +subplot(8,4,21:24) +plot(t,xt) +set(gca,'xticklabel',[],'xlim',[0 max(t)],'ylim',[-1 1]) +title('Clean target signal') +ylabel('Amplitude') +% +subplot(8,4,25:28) +plot(t,z_irm) +set(gca,'xticklabel',[],'xlim',[0 max(t)],'ylim',[-1 1]) +title('Target resynthesised from IRM') +ylabel('Amplitude') +% +subplot(8,4,29:32) +plot(t,z_ibm) +set(gca,'xlim',[0 max(t)],'ylim',[-1 1]) +title('Target resynthesised from IBM') +xlabel('Time [s]') +ylabel('Amplitude') diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/generateMixtures.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/generateMixtures.m new file mode 100644 index 0000000000000000000000000000000000000000..73011539c5ad9611dc992e2c00ba4bf3f1c59d1b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/generateMixtures.m @@ -0,0 +1,308 @@ +function mixtures = generateMixtures(targets,interferers,varargin) +%GENERATEMIXTURES Generate arrays of mixtures from targets and interferers. +% +% MIXTURES = IOSR.BSS.GENERATEMIXTURES(TARGETS,INTERFERERS) generates an +% array of MIXTURE objects using SOURCE objects TARGETS and INTERFERERS. +% Each mixture object contains one target element and SIZE(INTERFERERS,2) +% interferers (i.e. as many interferers as there are columns). How the +% inputs are combined is determined by the nature of the input or the +% 'COMBINE' setting (see below). +% +% MIXTURES = IOSR.BSS.GENERATEMIXTURES(...,'PARAMETER',VALUE) allows +% additional options to be specified. The options are listed below ({} +% indicate defaults). +% +% Independent variables +% +% 'azimuths' : {zeros([1 size(interferers,2)+1])} | array +% Specify the azimuths for the sources. The numeric array should +% have one more column than INTERFERERS. The first column is the +% target azimuth; subsequent columns are assigned to the +% interferer sources such that the Nth azimuth is assigned to the +% N-1th interferer column (N>1). Specifying this parameter will +% overwrite the source property. +% 'elevations' : {zeros([1 size(interferers,2)+1])} | array +% Specify the elevations for the sources. The specification is +% the same as for azimuths. +% 'sofa_paths' : {[]} | str | cellstr +% Specify the SOFA file(s) for the mixtures as one or more paths +% to SOFA files that are convolved with sources. The parameter +% should be a character array or cell array of strings. +% 'tirs' : {0} | scalar +% Specify the target-to-interferer ratios for the mixtures. +% +% TARGETS and INTERFERERS are also considered independent variables. +% +% Settings +% +% 'cache' : {false} | true +% Specify whether mixtures are cached as audio files, rather than +% being rendered ono-the-fly. The setting invokes +% mixture.write(). Files are named 'mixture-NNNN.wav' where NNNN +% is a counter padded with leading zeros. Target and interferer +% signals are also cached. +% 'combine' : 'all' | 'rows' +% Determines how the inputs are combined. If the independent +% variables have the same number of rows (ignoring empty or +% scalar variables) then the variables are combined on a +% row-by-row basis, with scalar variables applied to each row. +% This is the 'rows' option, which is the default when the above +% conditions apply; the conditions must be met in order to +% combine variables in this way. Alternatively, variables are +% combined in all combinations. This is the 'all' option, which +% is the default when variables have rows of different lengths; +% variables may each have any number of rows. +% 'decomposition' : {'stft'} | 'gammatone' +% The time-frequency decomposition used by the mixture. +% 'folder' : {'mixture_temp'} | str +% Specify a folder for storing cached audio files. +% 'fs' : {16000} | scalar +% Sampling frequency for the mixtures. +% +% See also IOSR.BSS.MIXTURE, IOSR.BSS.SOURCE, SOFALOAD. + +% Copyright 2016 University of Surrey. + + %% get input + + IVs = struct(... + 'azimuths',zeros([1 size(interferers,2)+1]),... + 'elevations',zeros([1 size(interferers,2)+1]),... + 'sofa_paths',[],... + 'tirs',0); + + settings = struct(... + 'fs',16000,... + 'cache',false,... + 'combine',[],... + 'folder','mixture_temp',... + 'decomposition','stft',... + 'stft',[],... + 'gammatone',[]); + + validOptions = [fieldnames(IVs); fieldnames(settings)]; + + %% check input + + % overwrite the default settings + IVs = overwrite(IVs,validOptions,varargin); + settings = overwrite(settings,validOptions,varargin); + + % decomposition settings + if isempty(settings.stft) + settings.stft = struct('win',1024','hop',512); + end + if isempty(settings.gammatone) + settings.gammatone = struct('cfs',iosr.auditory.makeErbCFs(20, settings.fs/2, 64),... + 'frame',round(0.01*settings.fs)); + end + + % check IVs + assert(isa(targets,'iosr.bss.source'), 'iosr:generateMixtures:invalidTargets', '''TARGETS'' must be of type iosr.bss.source') + assert(isa(interferers,'iosr.bss.source'), 'iosr:generateMixtures:invalidInterferers', '''INTERFERERS'' must be of type iosr.bss.source') + assert(isnumeric(IVs.azimuths), 'iosr:generateMixtures:invalidAzimuths', '''AZIMUTHS'' must be numeric') + assert(size(IVs.azimuths,2)==size(interferers,2)+1, 'iosr:generateMixtures:invalidAzimuths', '''AZIMUTHS'' should have one more column than INTERFERERS') + assert(isnumeric(IVs.elevations), 'iosr:generateMixtures:invalidElevations', '''ELEVATIONS'' must be numeric') + assert(size(IVs.elevations,2)==size(interferers,2)+1, 'iosr:generateMixtures:invalidElevations', '''ELEVATIONS'' should have one more column than INTERFERERS') + if ~isempty(IVs.sofa_paths) + if ischar(IVs.sofa_paths) + IVs.sofa_paths = cellstr(IVs.sofa_paths); + elseif ~iscellstr(IVs.sofa_paths) + error('iosr:generateMixtures:pathInvalid','sofa_paths should be a char array or cell array of strings') + end + end + + % check settings + assert(islogical(settings.cache), 'iosr:generateMixtures:invalidCache', '''CACHE'' must be logical') + assert(ischar(settings.folder), 'iosr:generateMixtures:invalidFolder', '''FOLDER'' must be a char array') + if ~isempty(settings.combine) + assert(ischar(settings.combine), 'iosr:generateMixtures:invalidCombine', '''COMBINE'' must be a char array') + end + assert(isnumeric(settings.fs) && isscalar(settings.fs), 'iosr:generateMixtures:invalidFs', '''FS'' must be a numeric scalar') + + % ensure column vectors + IVs.sofa_paths = IVs.sofa_paths(:); + IVs.tirs = IVs.tirs(:); + targets = targets(:); + + % append targets and interferers to IVs + IVs.targets = targets; + IVs.interferers = interferers; + + %% make mixtures + + % check if vars have equal number of rows (ignore scalar of empty) + [equal,iterations] = check_vars_equal_rows(IVs); + + % automatically determine combine method + if isempty(settings.combine) + if equal + settings.combine = 'rows'; + else + settings.combine = 'all'; + end + end + + var_size = vars_rows(IVs); + + % do some things according to combine mode + switch lower(settings.combine) + case 'all' + iterations = prod(max(var_size,1)); % recalculate if rows were equal + IV_size = [... + max(numel(IVs.targets),1),... + max(size(IVs.interferers,1),1),... + max(numel(IVs.sofa_paths),1),... + max(numel(IVs.tirs),1),... + max(size(IVs.azimuths,1),1),... + max(size(IVs.elevations,1),1)]; + case 'rows' + assert(equal, 'iosr:generateMixtures:rowsInvalidInput', 'Properties must have an equal number of rows if specifying ''COMBINE'' mode ''ROWS''') + otherwise + error('iosr:generateMixtures:unknownCombine','Unknown ''COMBINE'' property') + end + + % create the mixtures + if settings.cache + disp('Writing wav files.') + end + mixtures(iterations,1) = iosr.bss.mixture; % preallocate + for m = 1:iterations + switch lower(settings.combine) + % get settings for current iteration + case 'rows' + % read rows together + target = copy(getIV('targets',m)); + interferer = copy(getIV('interferers',m)); + sofa_path = getIV('sofa_paths',m); + tir = getIV('tirs',m); + azimuths = getIV('azimuths',m); + elevations = getIV('elevations',m); + case 'all' + % work through each variable separately + [n,p,q,r,s,t] = ind2sub(IV_size,m); + target = copy(getIV('targets',n)); + interferer = copy(getIV('interferers',p)); + sofa_path = getIV('sofa_paths',q); + tir = getIV('tirs',r); + azimuths = getIV('azimuths',s); + elevations = getIV('elevations',t); + end + % apply spatial settings to sources + target.azimuth = azimuths(1); + target.elevation = elevations(1); + for i = 1:length(interferer) + interferer(i).azimuth = azimuths(i+1); + interferer(i).elevation = elevations(i+1); + end + % calculate mixtures + mixtures(m,1) = iosr.bss.mixture(... + target,... + interferer,... + 'tir',tir,... + 'sofa_path',sofa_path,... + 'fs',settings.fs,... + 'decomposition',settings.decomposition,... + 'gammatone',settings.gammatone,... + 'stft',settings.stft); + if settings.cache + mixtures(m,1).write([settings.folder filesep sprintf('mixture-%05d.wav',m)]) + end + end + if settings.cache + disp('Done.') + end + + function val = getIV(field,row) + %GETIV retrieve independent variable + + % function to index into the option field + index = @(n,F) mod(n-1,size(F,1))+1; + + % return data + if isempty(IVs.(field)) % return empty + val = []; + else % return value + if ~iscellstr(IVs.(field)) + M = index(row,IVs.(field)); + val = IVs.(field)(M,:); + else + M = index(row,IVs.(field)(:)); + val = IVs.(field){M}; + end + end + + end + +end + +function opts = overwrite(opts,validOptions,vgin) +%OVERWRITE overwrite the default properties with varargin + + % count arguments + nArgs = length(vgin); + if round(nArgs/2)~=nArgs/2 + error('iosr:generateMixtures:nameValuePair','generateMixtures needs propertyName/propertyValue pairs') + end + optionNames = fieldnames(opts); + % overwrite defults + for pair = reshape(vgin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + opts.(optionNames{IX}) = pair{2}; + else + if ~any(strcmpi(pair{1},validOptions)) + error('iosr:generateMixtures:unknownOption',['''' pair{1} ''' is not a valid option']) + end + end + end +end + +function [equal,num] = check_vars_equal_rows(varargin) +%CHECK_VARS_EQUAL_ROWS check variables have the same number of elements +% +% CHECK_VARS_EQUAL_ROWS(A,B,C,...) and CHECK_VARS_EQUAL_ROWS(OPTS) checks +% the variables A, B, C, ..., or the structure OPTS, to test whether the +% variables/fields have the same number of elements. Scalar or empty +% variables/fields are ignored. + + % get number of elements in each variable/field + nums = max(vars_rows(varargin{:}),1); + + % determine equality + nums = nums(nums>1); + + if ~isempty(nums) + equal = all(nums==nums(1)); % determine equality + % return number of elements + if equal + num = nums(1); + else + num = prod(nums); + end + else + % one row + equal = true; + num = 1; + end + +end + +function num = vars_rows(varargin) +%VARS_ROWS return the number of rows in each variable +% +% VARS_ROWS(A,B,C,...) and VARS_ROWS(OPTS) returns the number of rows in +% variables A, B, C, ..., or the fields of structure OPTS. + + % convert struct to cell array + if isstruct(varargin{1}) && length(varargin)==1 + vgin = struct2cell(varargin{1}); + else + vgin = varargin; + end + + % return number of elements + num = cellfun(@(x) size(x,1),vgin); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/getFullMask.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/getFullMask.m new file mode 100644 index 0000000000000000000000000000000000000000..756b5815c40c0282ac7e87562f6c1a4d99562efb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/getFullMask.m @@ -0,0 +1,58 @@ +function m_full = getFullMask(m,frame_d,delay,kernel) +%GETFULLMASK Convert frame rate mask to a sample-by-sample mask +% +% M_FULL = IOSR.BSS.GETFULLMASK(M,FRAME_D) expands the time-frequency +% mask M, which has one unit for each frequency channel and frame of +% length FRAME_D (in samples), to a sample-by-sample mask. The mask M is +% a time-frequency mask, with one column for each frequency channel, and +% one row for each time frame. The resulting mask will have dimensions +% [FRAME_D*size(M,1) size(M,2)]. +% +% M_FULL = IOSR.BSS.GETFULLMASK(M,FRAME_D,DELAY) removes a delay from +% each frequency channel in the mask. DELAY is a vector, with the same +% number of elements as M has columns, containing a delay (in samples) +% that is removed from the corresponding frequency channel. The mask is +% subsequently zero-padded. +% +% M_FULL = IOSR.BSS.GETFULLMASK(M,FRAME_D,DELAY,KERNEL) allows smoothing +% to be applied to the full mask. By default, the full mask contains +% rectangular transitions at unit boundaries. Specifying KERNEL allows +% the transitions to be smoother, by convolving the full mask with a +% two-dimensional kernel (dimensions [frequency time]). The central part +% of the convolution is returned, so the centre of the KERNEL should be +% in the centre of the matrix. The kernel is normalised in order to +% ensure zero gain at DC. +% +% See also IOSR.BSS.RESYNTHESISE. + +% Copyright 2016 University of Surrey. + + + if nargin < 2 + error('iosr:getFullMask:nargin','Not enough input arguments') + end + + numchans = size(m,2); + frameCount = size(m,1); + + if nargin < 3 + delay = zeros(1,numchans); + end + if nargin < 4 + kernel = 1; + end + + % Create the sample-by-sample mask + m_full = zeros(frameCount*frame_d,numchans); + for i = 1:numchans + for j = 1:frameCount + m_full(((j-1)*frame_d+1):((j-1)*frame_d+1)+frame_d-1,i) = m(j,i); + end + m_full(:,i) = [m_full(delay(i)+1:end,i); zeros(delay(i),1)]; + end + + % convolve with kernel + kernel = kernel./sum(abs(kernel(:))); + m_full = conv2(m_full,kernel,'same'); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/idealMasks.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/idealMasks.m new file mode 100644 index 0000000000000000000000000000000000000000..0c9ac66f69c1a03c432fc40ae9d8e546e22cd238 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/idealMasks.m @@ -0,0 +1,61 @@ +function [irm,ibm] = idealMasks(st,si,q,a) +%IDEALMASKS Calculate ideal time-frequency masks from STFTs +% +% IRM = IOSR.BSS.IDEALMASKS(ST,SI) calculates the ideal ratio mask (IRM) +% using target STFT ST and interferer STFT SI. ST and SI must be the same +% size; IRM is the same size as ST and SI. +% +% [IRM,IBM] = IOSR.BSS.IDEALMASKS(...) returns the ideal binary mask +% (IBM). +% +% IRM = IOSR.BSS.IDEALMASKS(ST,SI,Q) uses the exponent Q to create an +% ideal sigmoidal mask by raising each of the time-frequency powers to Q. +% With Q=1 (default) the mask is the IRM. As Q->Inf the IRM will tend +% towards a binary mask. As Q->0 the mask will tend towards 0.5. +% +% [IRM,IBM] = IOSR.BSS.IDEALMASKS(ST,SI,Q,A) uses the threshold A to +% calculate the IBM. The threshold is in terms of the ratio of time +% frequency powers. With A=1 (default), the IBM is 1 when the target +% power is greater than the interferer power. Setting A=2, for example, +% requires the target power to be 6dB greater than the interference +% power. +% +% See also IOSR.BSS.APPLYMASK, IOSR.BSS.APPLYIDEALMASKS. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(isequal(size(st),size(si)), 'iosr:idealMasks:invalidInputs', 'ST and SI must be the same size') + + % check sigmoid + if nargin<3 + q = 1; + else + assert(isscalar(a), 'iosr:idealMasks:invalidQ', 'Q must be an scalar') + end + + % check threshold + if nargin<4 + a = 1; + else + assert(isscalar(a), 'iosr:idealMasks:invalidA', 'A must be an scalar') + end + + %% calculate masks + + % powers + St = abs(st).^2; + Si = abs(si).^2; + + % ideal ratio mask + irm = (St.^q)./((St.^q)+(Si.^q)); + irm(isnan(irm)) = 0; + + % ideal binary mask + if nargout>1 + ibm = +(St./Si>a); + ibm(isnan(ibm)) = 0; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/mixture.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/mixture.m new file mode 100644 index 0000000000000000000000000000000000000000..a32732f4af5a82088550c8fdd71df61c3d21956b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/mixture.m @@ -0,0 +1,1026 @@ +classdef mixture < iosr.dsp.audio +%MIXTURE Class of sound source separation mixture. +% +% iosr.bss.mixture objects contain information about a mixture of sound +% sources. +% +% IOSR.BSS.MIXTURE is a subclass of IOSR.DSP.AUDIO. +% +% IOSR.BSS.MIXTURE properties: +% azi_sep - The azimuthal separation of the widest sources +% (read-only) +% decomp - The result of the time-frequency decomposition +% (mixture) (read-only) +% decomp_i - The result of the time-frequency decomposition +% (interferer) (read-only) +% decomp_t - The result of the time-frequency decomposition +% (target) (read-only) +% decomposition - Set the time-frequency decomposition. The options +% are: +% 'stft' : short-time fourier transform +% (default) +% 'gammatone' : gammatone filterbank +% elevation - The median elevation of the mixture (read-only) +% filename_t - Name of the target audio file (based on the +% mixture filename) (read-only) +% filename_i - Name of the interferer audio file (based on the +% Mixture filename) (read-only) +% gammatone - Settings for the gammatone filterbank +% decomposition. The property is a structure +% containing the following fields: +% 'cfs' : the centre frequencies of the +% gammatone filterbank +% 'frame' : the frame length (in samples) +% sofa_path - Path to a SOFA file containing spatialisation data +% ibm - The ideal binary mask +% irm - The ideal ratio mask +% int_fns - A char array containing the filenames of all of +% the interfering sources (read-only) +% interferers - An array of interferer sources of type +% iosr.bss.source +% signal_t - The sampled data (target) (read-only) +% signal_i - The sampled data (interferer) (read-only) +% stft - Settings for the STFT decomposition. The property +% is a structure containing the following fields: +% 'hop' : the hop size of the STFT +% 'win' : the STFT window +% See iosr.dsp.stft for more information +% target - The target source of type iosr.bss.source +% tfPower - The (frame-based) time-frequency power (mixture) +% (read-only) +% tfPower_i - The (frame-based) time-frequency power +% (interferer) (read-only) +% tfPower_t - The (frame-based) time-frequency power (target) +% (read-only) +% tir - The target-to-interferer ratio (target or +% interferers are attenuated in order that their +% RMS amplitudes have this ratio) +% wdo - The w-disjoint orthogonality (read-only) +% wdo_lw - The loudness-weighted w-disjoint orthogonality +% (read-only) +% +% IOSR.BSS.MIXTURE methods: +% mixture - Create the mixture +% clearCache - Clears the internally cached data, reducing +% file size. +% copy - Create an independent copy of the mixture, its +% sources, and any rendered files +% applyMask - Apply a time-frequency mask +% deleteFiles - Delete the mixture audio files +% sound_t - Replay the target +% sound_i - Replay the interferer +% write - Save the mixture, target, and interferers to audio files +% Static methods: +% maskCentroids - Calculate the centroids of a time-frequency mask +% mixWdo - WDO of a mixture +% mixWdo_lw - Loudness-weighted WDO of a mixture +% mixWdo_Stokes - WDO calculated using Stokes's method +% +% Note that target and interferer properties may be modified as +% MIXTURE.TARGET.PROPERTY_NAME and MIXTURE.INTERFERERS(N).PROPERTY_NAME, +% except for the sampling frequency FS, which cannot be overridden. This +% ensures that the sampling frequencies are identical for the mixture and +% its sources. +% +% See also IOSR.DSP.AUDIO, IOSR.BSS.SOURCE, SOFALOAD, IOSR.DSP.STFT, +% IOSR.AUDITORY.GAMMATONEFAST. + +% Copyright 2016 University of Surrey. + +%TODO: Add more decompositions. + + properties (AbortSet) + decomposition = 'stft' % The time-frequency decomposition + gammatone = struct % Settings for the gammatone filterbank decomposition + sofa_path % Path to a SOFA file containing spatialisation data + stft = struct % Settings for the STFT decomposition + tir = 0 % The target to interferer ratio + interferers % An array of interferer sources of type iosr.bss.source + target % The target source of type iosr.bss.source + end + + properties (Dependent, SetAccess = protected) + signal % The sampled data (read-only) + end + + properties (Dependent, SetAccess = private) + azi_sep % The azimuthal separation of the widest sources (read-only) + decomp % The result of the time-frequency decomposition (mixture) (read-only) + decomp_i % The result of the time-frequency decomposition (interferer) (read-only) + decomp_t % The result of the time-frequency decomposition (target) (read-only) + elevation % The median elevation of the mixture (read-only) + filename_t % Name of the target audio file (read-only) + filename_i % Name of the interferer audio file (read-only) + ibm % Ideal binary mask (read-only) + irm % Ideal ratio mask (read-only) + int_fns % Filenames of all of the interfering sources (read-only) + numchans % Number of audio channels in the mixture (read-only) + signal_t % Return target (read-only) + signal_i % Return interferer (read-only) + tfPower % The time-frequency power (mixture) (read-only) + tfPower_i % The time-frequency power (interferer) (read-only) + tfPower_t % The time-frequency power (target) (read-only) + wdo % Return the w-disjoint orthogonality metric (read-only) + wdo_lw % Return the loudness-weighted w-disjoint orthogonality metric (read-only) + wdo_stokes % Return the w-disjoint orthogonality metric using Stokes's method (read-only) + end + + properties (Access = private) + cached_decomp % the cached mixture decomposition + decomp_cached = false % whether the mixture decomposition is cached + cached_decomp_i % the cached interferer decomposition + decomp_i_cached = false % whether the interferer decomposition is cached + cached_decomp_t % the cached target decomposition + decomp_t_cached = false % whether the target decomposition is cached + cached_tfPower % the cached mixture TF power + tfPower_cached = false % whether the mixture TF power is cached + cached_tfPower_i % the cached interferer TF power + tfPower_i_cached = false % whether the interferer TF power is cached + cached_tfPower_t % the cached target TF power + tfPower_t_cached = false % whether the target TF power is cached + end + + methods + + % constructor + function obj = mixture(target,interferers,varargin) + %MIXTURE Create a mixture + % + % OBJ = IOSR.BSS.MIXTURE(TARGET,INTERFERER) creates a mixture by + % summing together the target source and the interferer + % source(s). The sources are mixed together such that their RMS + % amplitudes are equal (target-to-interferer ratio is 0dB). The + % OBJ sampling rate is equal to the target sampling rate. + % Information about the sources' spatial location is ignored. + % + % OBJ = IOSR.BSS.MIXTURE(...,'PARAMETER',VALUE) allows additional + % options to be specified. The options are ({} indicate + % defaults): + % + % 'decomposition' : {'stft'} | 'gammatone' + % 'filename' : {[]} | str + % A filename used when writing the file with the write() + % method. The filename may also be set when calling the + % write() method. Filenames for the target and interferer + % are determined automatically, by append the filename + % with '_target' and '_interferer' respectively. + % 'fs' : {obj.target.fs} | scalar + % The sampling frequency of the mixture. All HRTFs and/or + % sources will be resampled to this frequency each time + % the signal is requested. + % 'gammatone' + % Settings for the gammatone filterbank + % decomposition. The property is a structure + % containing the following fields: + % 'cfs' : the centre frequencies of the gammatone + % filterbank (default is 64 channels + % equally spaced on the ERB scale between + % 20Hz and the Nyquist limit + % 'frame' : the frame length (in samples) (the + % default is 20ms) + % 'sofa_path' : {[]} | str + % A path to a SOFA file containing HRTFs that are + % convolved with sources in order to generate the + % mixture. + % 'stft' + % Settings for the STFT decomposition. The property + % is a structure containing the following fields: + % 'hop' : the hop size of the STFT (the default + % is 512) + % 'win' : the STFT window (the default is 1024) + % 'tir' : {0} | scalar + % The RMS ratio of the target and interfer sources. + % Interferer sources are individually set to this level + % prior to their summation. + % + % OBJ = IOSR.BSS.MIXTURE creates an empty mixture object with + % empty target and interferer sources. + % + % To speed up time-frequency operations, the IOSR.BSS.MIXTURE + % class caches time-frequency data internally, which can lead to + % large file sizes if the object is saved. Use the CLEARCACHE() + % method to empty the internal cache. + % + % Note that this is a handle class, as is IOSR.BSS.SOURCE. Target + % and interferer(s) are hence passed by reference. Use the COPY() + % method to create an independent copy of the mixture and its + % sources. + + if nargin > 0 + + assert(nargin>1, 'iosr:mixture:nargin', 'Not enough input arguments') + + propNames = {'filename','fs','sofa_path','tir','decomposition','stft','gammatone'}; + + % set sources + obj.target = target; + obj.interferers = interferers; + + % defaults + obj.fs = obj.target.fs; + obj.sofa_path = []; + obj.tir = 0; + obj.rendered = false; + + % default decomposition settings + obj.stft = struct('win',1024,'hop',512); + obj.gammatone = struct(... + 'cfs',iosr.auditory.makeErbCFs(20, obj.fs/2, 64),... + 'frame', round(0.01*obj.fs)... + ); + + % read parameter/value inputs + if nargin > 1 % if parameters are specified + obj.set_properties(varargin,propNames) + end + + % set sample rate to SOFA file if set and fs not specified + if ~isempty(obj.sofa_path) && all(~strcmp('fs',varargin)) + SOFAobj = SOFAload(obj.sofa_path); % load SOFA object + obj.fs = SOFAobj.Data.SamplingRate; + end + + % ensure fs for sources matches instance + obj.target.fs = obj.fs; + for n = 1:numel(obj.interferers) + obj.interferers(n).fs = obj.fs; + end + + % set parent + obj.target.parent = obj; + for n = 1:numel(obj.interferers) + obj.interferers(n).parent = obj; + end + + end + + end + + function z = applyMask(obj,m) + %APPLYMASK Apply a time-frequency mask to the mixture + % + % Z = IOSR.BSS.MIXTURE.APPLYMASK(M) applies the time-frequency + % mask M to the mixture. The mixture is transformed according to + % the objects decomposition settings. The transform is then + % multiplied with M. Lastly, the result is then inverse + % transformed (or reynthesised). The time-domain output Z is + % returned. + + switch lower(obj.decomposition) + case 'stft' + s = obj.decomp; + % correct dims + d = obj.stft_shifted_dims(s); + s = ipermute(s,d); + m = ipermute(m,d); + for c = 1:obj.numchans + % apply mask + z(:,c) = iosr.bss.applyMask( ... + s(:,:,c), ... + m(:,:,min(c,size(m,3))), ... + obj.stft.win, ... + obj.stft.hop, ... + obj.fs ... + ); %#ok<AGROW> + end + case 'gammatone' + x = obj.signal; + for c = 1:obj.numchans + z(:,c) = iosr.bss.resynthesise( ... + x(:,c), ... + obj.fs, ... + iosr.bss.cfs2fcs(obj.gammatone.cfs, obj.fs), ... + m(:,:,c), ... + 'frame_length', obj.gammatone.frame, ... + 'filter', 'sinc', ... + 'kernel', gausswin(obj.gammatone.frame) ... + ); %#ok<AGROW> + end + end + + z = obj.setlength(z,length(obj.signal)); + + end + + function sound_t(obj) + %SOUND_T Replay the target signal + % + % IOSR.BSS.MIXTURE.SOUND_T() replays the target signal. + + obj.replay(obj.signal_t) + + end + + function sound_i(obj) + %SOUND_I Replay the interferer signal + % + % IOSR.BSS.MIXTURE.SOUND_I() replays the interferer signal. + + obj.replay(obj.signal_i) + + end + + function write(obj,filename) + %WRITE Save the mixture to an audio file + % + % IOSR.BSS.MIXTURE.WRITE() writes the mixture to an audio file + % specified by MIXTURE.FILENAME, and also writes the target and + % interferer signals to automatically-determined file names + % (MIXTURE.FILENAME_T and MIXTURE.FILENAME_I respectively). + % + % IOSR.BSS.MIXTURE.WRITE(FILENAME) uses the specified FILENAME + % and updates MIXTURE.FILENAME. + + if exist('filename','var')==1 + fn = filename; + else + fn = obj.filename; + end + + if obj.rendered && exist(fn, 'file') == 2 + if strcmp(obj.filename,fn) + % nothing to do + else + copyfile(obj.filename,fn); + copyfile(obj.filename_t,obj.make_target_filename(fn)); + copyfile(obj.filename_i,obj.make_interferer_filename(fn)); + end + else + % check filename is valid + obj.filename = fn; + assert(ischar(obj.filename) && ~isempty(obj.filename),'iosr:mixture:invalidFilename','FILENAME must be a non-empty char array. Set filename as MIXTURE.FILENAME or MIXTURE.WRITE(FILENAME).') + + % normalize + M = obj.signal; + T = obj.signal_t; + I = obj.signal_i; + [~,gain] = obj.normalize([M T I]); + M = M.*gain; + T = T.*gain; + I = I.*gain; + + % ensure path + obj.ensure_path(obj.filename) + + % write audio files + audiowrite(obj.filename,M,obj.fs); + audiowrite(obj.filename_t,T,obj.fs); + audiowrite(obj.filename_i,I,obj.fs); + + % set flag to indicate mixture has been rendered to an audio file + obj.rendered = true; + + end + + end + + function deleteFiles(obj) + %DELETEFILES Delete the mixture audio files + + if exist(obj.filename, 'file') == 2 + delete(obj.filename); + end + if exist(obj.filename_t, 'file') == 2 + delete(obj.filename_t); + end + if exist(obj.filename_i, 'file') == 2 + delete(obj.filename_i); + end + obj.rendered = false; + + end + + function clearCache(obj) + %CLEARCACHE Clear the internal cache + + obj.updateCachedFalse(); + obj.cached_decomp = []; + obj.cached_decomp_i = []; + obj.cached_decomp_t = []; + obj.cached_tfPower = []; + obj.cached_tfPower_i = []; + obj.cached_tfPower_t = []; + end + + % set/validate properties + + % set decomposition + function set.decomposition(obj,val) + assert(any(strcmpi(val,{'stft','gammatone'})), 'iosr:mixture:invalidDecomposition', '''decomposition'' must be ''stft'' or ''gammatone'''); + obj.updateCachedFalse(); + obj.decomposition = val; + end + + % set gammatone settings + function set.gammatone(obj,val) + assert(isstruct(val), 'iosr:mixture:invalidGammatoneStruct', '''gammatone'' must be a struct') + assert(all(ismember(fieldnames(val)',{'cfs','frame'})), 'iosr:mixture:invalidGammatoneFields', 'gammatone structure must contain fields ''cfs'' and ''frame''') + obj.updateCachedFalse; + obj.gammatone = val; + end + + % set stft settings + function set.stft(obj,val) + assert(isstruct(val), 'iosr:mixture:invalidStftStruct', '''stft'' must be a struct') + assert(all(ismember(fieldnames(val)',{'win','hop'})), 'iosr:mixture:invalidStftFields', 'stft structure must contain fields ''win'' and ''hop''') + obj.updateCachedFalse; + obj.stft = val; + end + + % set tir + function set.tir(obj,val) + obj.tir = val; + obj.property_changed('tir',val); + end + + % validate sofa_path + function set.sofa_path(obj,val) + assert(ischar(val) || isempty(val), 'iosr:mixture:invalidSofaPath', 'sofa_path must be a char array or an empty array') + if ~isempty(val) + assert(exist(val,'file')==2, 'iosr:mixture:invalidSofaPath', 'SOFA file does not exist') + end + obj.sofa_path = val; + obj.property_changed('sofa_path',val); + end + + % validate interferers + function set.interferers(obj,val) + assert(isa(val,'iosr.bss.source'), 'iosr:mixture:invalidInterferers', 'INTERFERERS must be of type source') + obj.interferers = val; + obj.property_changed('interferers',val); + end + + % validate target + function set.target(obj,val) + assert(isa(val,'iosr.bss.source') && numel(val)==1, 'iosr:mixture:invalidTarget', 'TARGET must be a scalar of type source') + obj.target = val; + obj.property_changed('target',val); + end + + % dependent properties + + % get decomposition result (mixture) + function s = get.decomp(obj) + if obj.decomp_cached + s = obj.cached_decomp; + else + s = obj.decompose(obj.signal); + obj.cached_decomp = s; + obj.decomp_cached = true; + end + end + + % get decomposition result (interferer) + function s = get.decomp_i(obj) + if obj.decomp_i_cached + s = obj.cached_decomp_i; + else + s = obj.decompose(obj.signal_i); + obj.cached_decomp_i = s; + obj.decomp_i_cached = true; + end + end + + % get decomposition result (target) + function s = get.decomp_t(obj) + if obj.decomp_t_cached + s = obj.cached_decomp_t; + else + s = obj.decompose(obj.signal_t); + obj.cached_decomp_t = s; + obj.decomp_t_cached = true; + end + end + + % get azimuthal separation + function s = get.azi_sep(obj) + [s,~] = get_loc(obj); + end + + % get median elevation + function e = get.elevation(obj) + [~,e] = get_loc(obj); + end + + % target filename + function fn = get.filename_t(obj) + fn = obj.make_target_filename(obj.filename); + end + + % interferer filename + function fn = get.filename_i(obj) + fn = obj.make_interferer_filename(obj.filename); + end + + % ibm + function m = get.ibm(obj) + switch lower(obj.decomposition) + case 'stft' + for c = 1:obj.numchans + [~,m(:,:,c)] = iosr.bss.idealMasks( ... + obj.decomp_t(:,:,c), ... + obj.decomp_i(:,:,c) ... + ); %#ok<AGROW> + end + case 'gammatone' + T = obj.tfPower_t; + I = obj.tfPower_i; + m = +(T>I); + end + end + + % irm + function m = get.irm(obj) + switch lower(obj.decomposition) + case 'stft' + for c = 1:obj.numchans + m(:,:,c) = iosr.bss.idealMasks( ... + obj.decomp_t(:,:,c), ... + obj.decomp_i(:,:,c) ... + ); %#ok<AGROW> + end + case 'gammatone' + T = obj.tfPower_t; + I = obj.tfPower_i; + m = T./(T+I); + end + m(isnan(m) | isinf(m)) = 0; + end + + % filenames of all interferers + function fns = get.int_fns(obj) + for n = 1:length(obj.interferers) + if n==1 + fns = obj.interferers(n).filename; + else + fns = [fns ', ' obj.interferers(n).filename]; %#ok<AGROW> + end + end + end + + % number of audio channels + function n = get.numchans(obj) + if obj.hrtf_is_set() + s = SOFAload(obj.sofa_path); + n = size(s.Data.IR,2); + else + iN = [obj.interferers.numchans]; + n = max([obj.target.numchans; iN(:)]); + end + end + + % return target signal + function signal_t = get.signal_t(obj) + if obj.rendered && exist(obj.filename_t,'file')==2 % don't bother calculating + signal_t = audioread(obj.filename_t); + else % calculate + signal_t = return_source(obj,obj.target); + if obj.tir<0 + % attenuate according to TIR + Trms = iosr.dsp.rms(signal_t(:)); + Irms = iosr.dsp.rms(obj.signal_i(:)); + signal_t = signal_t./(Trms/Irms); % match to interferer + signal_t = signal_t.*(10^(obj.tir/20)); % attenuate + end + end + end + + % return interferer signal + function signal_i = get.signal_i(obj) + if obj.rendered && exist(obj.filename_i,'file')==2 % don't bother calculating + signal_i = audioread(obj.filename_i); + else % calculate + signal_i = zeros(1, obj.numchans); % initialise + maxlength = 0; % initialise + for n = 1:numel(obj.interferers) % step through each interferer + % source signal (ensure 2-channel) + s = obj.return_source(obj.interferers(n)); + % ensure signals are same length, or zero-pad + maxlength = max([length(s) maxlength]); + s = obj.setlength(s,maxlength); + signal_i = obj.setlength(signal_i,maxlength); + % add source to interferer + signal_i = signal_i + s; + end + if obj.tir>=0 + % attenuate according to TIR + Trms = iosr.dsp.rms(obj.signal_t(:)); + Irms = iosr.dsp.rms(signal_i(:)); + signal_i = signal_i./(Irms/Trms); % match to interferer + signal_i = signal_i./(10^(obj.tir/20)); % attenuate + end + end + end + + % return mixture signal + function signal = get.signal(obj) + if obj.rendered && exist(obj.filename,'file')==2 % don't bother calculating + signal = audioread(obj.filename); + else % calculate + % return target and interferers + T = obj.signal_t; + I = obj.signal_i; + % mix, ensuring equal length + maxlength = max([length(T) length(I)]); + signal = obj.setlength(T,maxlength) + obj.setlength(I,maxlength); + end + end + + % return time-frequency power (mixture) + function val = get.tfPower(obj) + if obj.tfPower_cached + val = obj.cached_tfPower; + else + val = obj.tf_power(obj.decomp); + obj.cached_tfPower = val; + obj.tfPower_cached = true; + end + end + + % return time-frequency power (interferer) + function val = get.tfPower_i(obj) + if obj.tfPower_i_cached + val = obj.cached_tfPower_i; + else + val = obj.tf_power(obj.decomp_i); + obj.cached_tfPower_i = val; + obj.tfPower_i_cached = true; + end + end + + % return time-frequency power (target) + function val = get.tfPower_t(obj) + if obj.tfPower_t_cached + val = obj.cached_tfPower_t; + else + val = obj.tf_power(obj.decomp_t); + obj.cached_tfPower_t = val; + obj.tfPower_t_cached = true; + end + end + + % return wdo + function w = get.wdo(obj) + w = obj.mixWdo(abs(obj.decomp_t), abs(obj.decomp_i)); + end + + % return loudness-weighted wdo + function w = get.wdo_lw(obj) + [S,f] = obj.decompose(obj.signal_t); + w = obj.mixWdo_lw(abs(S), abs(obj.decomp_i), f); + end + + % return Stokes's wdo + function w = get.wdo_stokes(obj) + w = obj.mixWdo_Stokes(obj.irm); + end + + end + + methods (Static, Access = public) + + function [C, Ct, Cf] = maskCentroids(m, fs, decomposition, nfft, hop) + %MASKCENTROIDS Return various time-frequency mask centroids + % + % C = IOSR.BSS.MIXTURE.MASKCENTROIDS(M,FS,NFFT,HOP) returns the + % time-frequency mask centroid C calculated from mask M, sample + % rate FS, FFT-length NFFT, and and hop size HOP. The mask + % centroid is a unitless measure of the centroid of a + % time-frequency mask. The mask centroid is a measure of the + % frequency content of a time-frequency mask. + % + % [C,Ct,Cf] = IOSR.BSS.MIXTURE.MASKCENTROIDS(...) returns the + % time-related spectral centroid (in Hz) Ct and the + % frequency-related spectral centroid (in seconds) Cf. + + assert(ischar(decomposition), 'iosr:mixture:invalidDecomposition', '''decomposition'' must be a char array') + + numchans = size(m,3); + frame_frequency = fs/hop; + switch lower(decomposition) + case 'stft' + assert(isscalar(nfft), 'iosr:mixture:invalidNfft', '''nfft'' must be a scalar') + quefrency = fs/nfft; + case 'gammatone' + assert(isvector(nfft), 'iosr:mixture:invalidNfft', '''cfs'' must be a scalar') + cfs = nfft; + quefrency = fs/min(diff(iosr.auditory.erbRate2hz(cfs))); + otherwise + error('iosr:mixture:unknownDecomp','Unknown decomposition.') + end + + f_dct = repmat((((0:size(m,1)-1)./size(m,1)).*frame_frequency)',1,size(m,2)); + c_dct = repmat(((0:size(m,2)-1)./size(m,2)).*quefrency,size(m,1),1); + + C = zeros(1, numchans); + Ct = zeros(1, numchans); + Cf = zeros(1, numchans); + for c = 1:numchans + X = abs(dct(m(:,:,c))); + sumX = sum(sum(X)); + C(c) = sum(sum(X.*f_dct.*c_dct))./sumX; + Ct(c) = sum(sum(X.*f_dct))./sumX; + Cf(c) = sum(sum(X.*c_dct))./sumX; + end + + end + + function w = mixWdo(st, si) + %MIXWDO Calculate the mixture w-disjoint orthogonality + % + % W = IOSR.BSS.MIXTURE.MIXWDO(St,Si) calculates the w-disjoint + % orthogonality of a target and interferer(s) from their + % time-frequency magnitudes St and Si. The w-disjoint + % orthogonality is estimated by the two-dimensional + % cross-correlation coefficient of the source magnitudes. + + numchans = size(st,3); + w = zeros(1,numchans); + for c = 1:numchans + w(c) = corr2(st(:,:,c),si(:,:,c)); + end + + end + + function w = mixWdo_lw(st, si, f) + %MIXWDO_LW Calculate the loudness-weighted w-disjoint orthogonality + % + % W = IOSR.BSS.MIXTURE.MIXWDO_LW(St,Si,F) calculates the + % loudness-weighted w-disjoint orthogonality of a target and + % interferer(s) from their time-frequency magnitudes St and Si. + % The weighting is calculated from the ISO-226 65-phon equal + % loudness contour using the frequency vector F containing the + % frequency of each bin of St and Si. The magnitudes are + % multiplied with the loudness-weighting factor prior to + % calculating the WDO. + % + % See also IOSR.AUDITORY.LOUDWEIGHT. + + lw = iosr.auditory.loudWeight(f(:), 65)'; + lw = repmat(lw,size(st,1),1,size(st,3)); + w = iosr.bss.mixture.mixWdo(st.*lw,si.*lw); + + end + + function w = mixWdo_Stokes(irm) + %MIXWDO_LW Calculate the w-disjoint orthogonality using Stokes's method + % + % W = IOSR.BSS.MIXTURE.MIXWDO_STOKES(IRM) calculates the + % w-disjoint orthogonality using Stokes's method [1]. The method + % utilizes the ideal ratio mask (IRM), which is 0.5 when the + % target and interferer have equal power, and tends towards 0 or + % 1 when either source dominates. + % + % References + % + % [1] Stokes, Tobias W. (2015) Improving the perceptual quality + % of single-channel blind audio source separation. Doctoral + % thesis, University of Surrey. + + h = hist(irm(:),11)./numel(irm); + hw = [0:0.2:1 0.8:-0.2:0]; + w = sum(h.*hw); + + end + + end + + methods (Static, Access = private) + + function y = setlength(x,signal_length) + %SETLENGTH Crop or zero-pad signal to specified length + + d = size(x); + if size(x,1)>signal_length % need to crop + subsidx = [{1:signal_length} repmat({':'},1,ndims(x)-1)]; + y = x(subsidx{:}); + elseif size(x,1)<signal_length % need to zero-pad + y = [x; zeros([signal_length-size(x,1),d(2:end)])]; + else % do nothing + y = x; + end + + end + + function fn = append_filename(filename,append) + %APPEND_FILENAME Append strings to MIXTURE.FILENAME + + if isempty(filename) % do nothing if filename is empty + fn = []; + else % append + [filepath,name,ext] = fileparts(filename); % break up filename + newname = [name append ext]; % append + if isempty(filepath) % only filename specified + fn = newname; + else % path specified + fn = [filepath filesep newname]; + end + end + + end + + function d = stft_shifted_dims(s) + %STFT_SHIFTED_DIMS Dim order for STFT, swapping time and bins + + dim_order = 1:ndims(s); + if ndims(s) > 2 %#ok<ISMAT> + d = dim_order([2 1 dim_order(3:end)]); + else + d = [2 1]; + end + end + + end + + methods (Access = private) + + function c = hrtf_is_set(obj) + %HRTF_IS_SET Determine whether HRTFs are specified + + c = ~isempty(obj.sofa_path); + + end + + function s = return_source(obj,src) + %RETURN_SOURCE Return signal from specified source + + % ensure correct channel count + if ~src.precomposed && obj.hrtf_is_set() + src.numchans = 1; % signal will be spatialised + else + src.numchans = obj.numchans; % signal will be mixed directly + end + x = src.signal; + % return/convolve signal + if ~src.precomposed && obj.hrtf_is_set() % convolve + s = obj.spat(obj.sofa_path,x,src.azimuth,src.elevation,obj.fs); + else % return directly + s = x; + end + + end + + function [s,em] = get_loc(obj) + %GET_LOC Return location information + + % get angles from the sources + a = zeros(numel(obj.interferers)+1,1); + e = a; + for n = 1:numel(obj.interferers) + a(n) = obj.interferers(n).azimuth; + e(n) = obj.interferers(n).elevation; + end + a(end) = obj.target.azimuth; + e(end) = obj.target.elevation; + + % get separation + if any(a<0) % assume angles are -179:180 + s = abs(max(a)-min(a)); + else % assume angles are 0:359 + s = (360-max(a))+min(a); + end + s = mod(s,180); + + % get elevation + em = median(e); + + end + + function fn = make_target_filename(obj,filename) + %MAKE_TARGET_FILENAME Return the automated target filename + + fn = obj.append_filename(filename,'_target'); + + end + + function fn = make_interferer_filename(obj,filename) + %MAKE_INTERFERER_FILENAME Return the automated interferer filename + + fn = obj.append_filename(filename,'_interferer'); + + end + + function [s,f,t] = decompose(obj,x) + %DECOMPOSE Transform a signal into the time-frequency domain + + switch lower(obj.decomposition) + case 'stft' + for c = 1:obj.numchans + [s(:,:,c),f,t] = iosr.dsp.stft(x(:,c), obj.stft.win, obj.stft.hop, obj.fs); %#ok<AGROW> + end + % put time down column + s = permute(s,obj.stft_shifted_dims(s)); + s = obj.setlength(s, obj.get_frame_count(length(obj.signal))); + case 'gammatone' + f = obj.gammatone.cfs; + t = (0:length(x)-1)./obj.fs; + for c = 1:obj.numchans + s(:,:,c) = iosr.auditory.gammatoneFast(x(:,c), obj.gammatone.cfs, obj.fs); %#ok<AGROW> + end + end + + end + + function y = tf_power(obj,x) + %TF_POWER Calculate TF power. + + switch lower(obj.decomposition) + case 'gammatone' + frame_count = obj.get_frame_count(size(x,1)); + y = zeros(frame_count,length(obj.gammatone.cfs),obj.numchans); + for m = 1:frame_count + samples = (m-1)*obj.gammatone.frame+1:m*obj.gammatone.frame; + for N = 1:size(x,3) + y(m,:,N) = sum(x(samples,:,N).^2); + end + end + case 'stft' + y = abs(x).^2; + end + + end + + function frame_count = get_frame_count(obj, signal_length) + %GET_FRAME_COUNT Calculate number of T-F frames. + + assert(isscalar(signal_length), 'iosr:mixture:invalidSignalLength', 'SIGNAL_LENGTH must be a scalar.') + + switch lower(obj.decomposition) + case 'gammatone' + frame_count = floor(signal_length/obj.gammatone.frame); + case 'stft' + frame_count = fix((signal_length-(obj.nfft-obj.stft.hop))/obj.stft.hop); + end + + end + + function n = nfft(obj) + %NFFT return the fft length + + if isscalar(obj.stft.win) + n = obj.stft.win; + else + n = length(obj.stft.win); + end + end + + function updateCachedFalse(obj) + obj.decomp_cached = false; + obj.decomp_i_cached = false; + obj.decomp_t_cached = false; + obj.tfPower_cached = false; + obj.tfPower_i_cached = false; + obj.tfPower_t_cached = false; + end + + end + + methods(Access = protected) + + function property_changed(obj,name,val) + %PROPERTY_CHANGED handle property changes + + obj.rendered = false; + obj.updateCachedFalse(); + + switch lower(name) + case 'fs' + obj.target.fs = val; + for n = 1:numel(obj.interferers) + obj.interferers(n).fs = val; + end + end + + end + + function cpObj = copyElement(obj) + %COPYELEMENT Overload copy method with additional functionality + + % Make a shallow copy of all properties + cpObj = copyElement@iosr.dsp.audio(obj); + + % Changed rendered file name + cpObj.filename = obj.append_filename(cpObj.filename,'_copy'); + + % copy files + if obj.rendered + if exist(obj.filename,'file')==2 + copyfile(obj.filename,cpObj.filename) + end + if exist(obj.filename_i,'file')==2 + copyfile(obj.filename_i,cpObj.filename_i) + end + if exist(obj.filename_t,'file')==2 + copyfile(obj.filename_t,cpObj.filename_t) + end + end + + % Make a deep copy of target and interferers + cpObj.target = copy(obj.target); + cpObj.interferers = copy(obj.interferers); + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/resynthesise.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/resynthesise.m new file mode 100644 index 0000000000000000000000000000000000000000..6fb2d521b2d5810e613f682f42f74e662256dc7c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/resynthesise.m @@ -0,0 +1,152 @@ +function output = resynthesise(x,fs,cfs,m,varargin) +%RESYNTHESISE Resynthesise a target from a time-frequency mask +% +% OUTPUT = IOSR.BSS.RESYNTHESISE(X,FS,CFS,M) takes an input vector X, +% sampled at FS Hz, and applies the time-frequency mask M. The mask M is +% a matrix, with one column for each frequency channel, and one row for +% each sample. A row may also correspond to a frame - see 'frame_length' +% option below. The centre frequency of each column is contained in CFS. +% +% OUTPUT = IOSR.BSS.RESYNTHESISE(X,FS,CFS,M,'PARAMETER',VALUE) allows a +% number of options to be specified. The options are: +% +% % ({} indicates the default value) +% +% 'frame_length' : {1} | scalar +% The frame length for each time-frequency unit in M, in samples. +% 'delay' : {zeros(size(m,2),1)} | vector +% The delay in the filterbank when the time-frequency mask M was +% calculated. The delay is removed only when 'frame_length' > 1 and +% the full mask must be reconstructed. The value should be a vector +% whose length is equal to the number of columns in M; delay(n) is +% the delay in frequency band cfs(n). The delay does not affect the +% ouput of the reconstruction filters, since the filters are +% zero-phase. +% 'kernel' : {1} | vector +% Allows smoothing to be applied to the full mask. See +% IOSR.BSS.GETFULLMASK for more details. +% 'filter' : {'gammatone'} | 'sinc' +% Allows the reconstruction filter to be specified. By default a +% gammatone filterbank is used, and cfs corresponds to the filter +% centre frequencies. Alternatively a series sinc band-pass filters +% can be used. In this case it is assumed that the frequencies in cfs +% correspond to the upper cut-off frequencies of the sinc filters. +% The function IOSR.BSS.CFS2FCS can be used to calculate the cut-off +% frequencies. +% 'order' : {fs} | scalar +% The sinc filter order. +% +% Algorithm +% +% The algorithm has the following steps: +% 1) If necessary, obtain the full (smoothed) binary mask. See +% IOSR.BSS.GETFULLMASK. +% 2) Pass the vector x through the reconstruction filterbank, with +% centre/cut-off frequencies cfs. +% 3) Multiply the full mask with the output of the filterbank. +% 4) Sum the responses of the filterbank to produce a vector the same +% size as x. +% +% See also IOSR.BSS.CFS2FCS, IOSR.BSS.GETFULLMASK, IOSR.BSS.SINCFILTER. + +% Copyright 2016 University of Surrey. + + %% parse input + + if nargin<4 + error('iosr:resynthesise:tooFewInputArgs','Not enough input arguments') + end + + numchans = size(m,2); + + options = struct(... + 'frame_length',1,... + 'delay',zeros(numchans,1),... + 'kernel',1,... + 'filter','gammatone',... + 'order',fs); + + % read parameter/value inputs + if nargin > 4 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:resynthesise:nameValuePairs','RESYNTHESISE needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:resynthesise:unknownParameter','%s is not a recognized parameter name',pair{1}) + end + end + end + + delay = options.delay; + kernel = options.kernel; + outfilter = options.filter; + frame_d = options.frame_length; + order = options.order; + + % validate + assert(isvector(x) && isnumeric(x), 'iosr:resynthesise:invalidX', 'x must be a vector.'); + assert(all(round(delay)==delay), 'iosr:resynthesise:invalidDelay', 'Values in ''delay'' must be integers.'); + assert(length(delay)==numchans && isnumeric(delay), 'iosr:resynthesise:invalidDelay', 'The ''delay'' parameter must be a numeric vector the same length as the number of columns in m.'); + assert(ischar(outfilter), 'iosr:resynthesise:invalidFilter', 'The ''filter'' option must be a char array (string).'); + assert(round(frame_d)==frame_d && isscalar(frame_d), 'iosr:resynthesise:invalidFrame', '''frame_length'' must be a integer scalar.'); + assert(isnumeric(kernel), 'iosr:resynthesise:invalidKernel', '''kernel'' must be numeric.'); + assert(isvector(cfs) && length(cfs)==numchans && isnumeric(cfs), 'iosr:resynthesise:invalidCfs', 'cfs must be a vector with the same number of elements as there are columns of m.') + + %% get sample-by-sample masks + + if frame_d>1 + m_full = iosr.bss.getFullMask(m,frame_d,delay,kernel); + else + m_full = m; + end + + % crop or zero-pad x to match mask + if size(m_full,1)<length(x) + xpad = x(1:length(m_full)); + elseif size(m_full,1)>length(x) + xpad = [x; zeros(size(m_full,1)-length(x),1)]; + else + xpad = x; + end + + %% Pass x through reconstruction filterbank + + switch lower(outfilter) + case 'gammatone' + z = iosr.auditory.gammatoneFast(xpad,cfs,fs,true); % phase aligned GTFB + case 'sinc' + fcs = [0 cfs]; + z = zeros(length(xpad),numchans); + for i = 1:numchans + z(:,i) = iosr.dsp.sincFilter(xpad,fcs(i:i+1)./(fs/2),order)'; + end + otherwise + error('Unknown ''filter'' option specified') + end + + %% create output + + % apply mask + z = z.*m_full; + + % Sum to create waveforms + output = sum(z,2); + + % crop or zero-pad output to match input + if length(output)>length(x) + output = output(1:length(x)); + elseif length(output)<length(x) + output = [output; zeros(length(x)-length(output),1)]; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/source.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/source.m new file mode 100644 index 0000000000000000000000000000000000000000..bdc440efa2efd095a3fd014683b4da2776bd74a5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+bss/source.m @@ -0,0 +1,224 @@ +classdef source < iosr.dsp.audio +%SOURCE Class of sound source separation source. +% +% iosr.bss.source objects contain information about a sound source +% (including its spatial location). iosr.bss.source objects are passed to +% iosr.bss.mixture objects in order to create a mixture. +% +% IOSR.BSS.SOURCE is a subclass of IOSR.DSP.AUDIO. +% +% IOSR.BSS.SOURCE properties: +% azimuth - Azimuth of the source +% elevation - Elevation of the source +% numchans - Number of audio channels in the source +% precomposed - Logical flag indicating whether the source should be +% spatialised +% +% IOSR.BSS.SOURCE methods: +% source - Create a source object +% copy - Create an independent copy of the source (but not its +% audio file) +% write - Write the source audio file (and resample/downmix) +% +% See also IOSR.DSP.AUDIO, IOSR.BSS.MIXTURE. + +% Copyright 2016 University of Surrey. + + properties (AbortSet) + azimuth % Azimuth of the source + elevation % Elevation of the source + numchans % Number of audio channels in the source + precomposed % Logical flag indicating whether the source should be spatialised + end + + properties (Dependent, SetAccess = protected) + signal % The sampled data (read-only) + end + + properties (GetAccess = private, SetAccess = public) + parent + end + + methods + + % constructor + function obj = source(filename,varargin) + %SOURCE Create a source object + % + % OBJ = IOSR.BSS.SOURCE(FILENAME) creates a source whose signal + % is contained in the audio file FILENAME. The source will have + % an azimuth and elevation of 0. The number of channels and + % sampling frequency will be determined by the audio file. + % + % OBJ = IOSR.BSS.SOURCE(...,'PARAMETER',VALUE) allows additional + % options to be specified. The options are ({} indicate + % defaults): + % + % 'azimuth' : {0} | scalar + % The azimuth of the source for rendering. + % 'elevation' : {0} | scalar + % The elevation of the source for rendering. + % 'fs' : {fs of FILENAME} | scalar + % The sampling frequency of the source. If the sampling + % frequency of the audio file FILENAME does not match, + % the audio file will be resampled each time the signal + % is requested. + % 'precomposed' : {false} | true + % Logical flag indicating whether the source should be + % spatialised. By default it is assumed that the source + % is a point source (irrespective of its channel count), + % and it will be spatialised. When set to true, the + % source will be summed directly with the spatial signal. + % 'numchans' : {numchans of FILENAME} | scalar + % The number of channels in the source. If this does not + % match the channel count of the audio file FILENAME, the + % audio file will be up-/down-mixed each time the signal + % is requested. + % + % The FS and NUMCHANS parameters do not affect the underlying + % audio file, but are implemented on-the-fly each time the signal + % is requested. To render the changes to a new audio file, use + % the write() method. + % + % OBJ = IOSR.BSS.SOURCE creates an empty source object. + % + % Note that this is a handle class. Sources are hence passed by + % reference. Use the COPY() method to create an independent copy + % of the source. + % + % See also IOSR.DSP.AUDIO.UP_DOWN_MIX. + + if nargin > 0 + + propNames = {'azimuth','elevation','fs','precomposed','numchans'}; + + obj.filename = filename; + info = audioinfo(obj.filename); + + % defaults + obj.azimuth = 0; + obj.elevation = 0; + obj.precomposed = false; + obj.fs = info.SampleRate; + obj.numchans = info.NumChannels; + obj.rendered = false; + + % read parameter/value inputs + if nargin > 1 % if parameters are specified + obj.set_properties(varargin,propNames) + end + + end + + end + + function write(obj,filename) + %WRITE Write the source audio file (and resample/downmix) + % + % IOSR.BSS.SOURCE.WRITE() overwrites the source's audio file. If + % the source audio file's sampling rate and/or channel count do + % not match the object's properties, then the audio file will be + % resampled and/or up- or down-mixed accordingly. + % + % IOSR.BSS.SOURCE.WRITE(FILENAME) writes the audio file to the + % specified file FILENAME and updates SOURCE.FILENAME. + % + % See also IOSR.DSP.AUDIO.UP_DOWN_MIX. + + % overwrite filename if one is specified + if exist('filename','var')==1 + obj.filename = filename; + end + + assert(~isempty(obj.filename), 'iosr:source:invalidFile', 'SOURCE.FILENAME is empty.') + + % ensure path exists + obj.ensure_path(obj.filename) + + % write new file and update filename + audiowrite(obj.filename,obj.normalize(obj.signal),obj.fs); + obj.rendered = true; + + end + + % validate properties + + % validate azimuth + function set.azimuth(obj,val) + assert(isscalar(val), 'iosr:source:invalidAzimuth', 'AZIMUTH must be a scalar') + obj.azimuth = val; + obj.property_changed('azimuth',val); + end + + % validate elevation + function set.elevation(obj,val) + assert(isscalar(val), 'iosr:source:invalidElevation', 'ELEVATION must be a scalar') + obj.elevation = val; + obj.property_changed('elevation',val); + end + + % validate numchans + function set.numchans(obj,val) + assert(isscalar(val), 'iosr:source:invalidNumchans', 'NUMCHANS must be a scalar') + obj.numchans = val; + obj.property_changed('numchans',val); + end + + % validate precomposed + function set.precomposed(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:source:invalidPrecomposed', 'PRECOMPOSED property must be true or false') + obj.precomposed = val; + obj.property_changed('precomposed',val); + end + + % dependent properties + + % get dependent property signal + function signal = get.signal(obj) + + % read audio file + [signal,fs2] = audioread(obj.filename); + + % do more stuff if differences not rendered + if ~obj.rendered + N = size(signal,2); + + if fs2~=obj.fs % resample + signal = resample(signal,obj.fs,fs2); + end + if N~=obj.numchans % downmix + signal = iosr.dsp.audio.up_down_mix(signal,obj.numchans); + end + end + + end + + end + + methods(Access = protected) + + function property_changed(obj,name,val) + %PROPERTY_CHANGED handle property changes + + obj.rendered = false; + + switch lower(name) + case 'fs' + if isa(obj.parent,'mixture') && obj.parent.fs~=val + obj.parent.fs = val; + end + end + + end + + function cpObj = copyElement(obj) + %COPYELEMENT Overload copy method with additional functionality + + % Make a shallow copy of all properties + cpObj = copyElement@iosr.dsp.audio(obj); + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/audio.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/audio.m new file mode 100644 index 0000000000000000000000000000000000000000..e6b5888395104c86b929f8027c642f5530a2c8de --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/audio.m @@ -0,0 +1,239 @@ +classdef (Abstract) audio < matlab.mixin.Copyable +%AUDIO Abstract superclass providing audio-related properties and methods. +% +% The IOSR.DSP.AUDIO superclass is an abstract class that defines +% audio-related properties and methods. As an abstract class, it cannot +% be instantiated. +% +% IOSR.DSP.AUDIO is a subclass of MATLAB.MIXIN.COPYABLE, which is a +% subclass of the HANDLE class. Hence subclasses of AUDIO are handle +% classes. +% +% IOSR.DSP.AUDIO properties: +% filename - Name of the corresponding audio file +% fs - Sampling frequency (Hz) +% signal - The sampled data (read-only) +% +% IOSR.DSP.AUDIO methods: +% sound - Replay the audio signal +% Static methods: +% up_down_mix - Remix a source to a designated channel count +% normalize - Normalize an audio signal +% spat - Spatialise a sound using a SOFA file +% +% See also IOSR.BSS.MIXTURE, IOSR.BSS.SOURCE, HANDLE, +% MATLAB.MIXIN.COPYABLE. + +% Copyright 2016 University of Surrey. + + properties (AbortSet) + filename % Name of the audio file + fs = 16000 % Sampling frequency (Hz) + end + + properties (Abstract, Dependent, SetAccess = protected) + signal % The sampled data (read-only) + end + + properties (Access = protected) + rendered = false % Flag indicates whether files match object + end + + methods % public methods + + function obj = audio(filename,fs) + %AUDIO Create the audio object + + if nargin > 0 + obj.filename = filename; + end + if nargin > 1 + obj.fs = fs; + end + + end + + function sound(obj) + %SOUND Replay the audio signal + % + % IOSR.DSP.AUDIO.SOUND() replays the audio signal. + + obj.replay(obj.signal) + + end + + % validate properties + + % validate filename + function set.filename(obj,val) + assert(ischar(val) || isempty(val), 'iosr:audio:invalidFile', 'FILENAME must be a char array or an empty array') + obj.filename = val; + obj.property_changed('filename',val); + end + + % validate fs + function set.fs(obj,val) + assert(isscalar(val), 'iosr:audio:invalidFs', 'FS must be a scalar') + assert(val > 0, 'iosr:audio:invalidFs', 'FS must be greater than 0') + obj.fs = val; + obj.property_changed('fs',val); + end + + end + + methods (Access = protected) + + function property_changed(obj,name,val) %#ok<INUSD> + %PROPERTY_CHANGED handle property changes + + obj.rendered = false; + end + + function replay(obj,x) + %REPLAY Replay any audio signal + + sound(obj.normalize(x),obj.fs) % replay + + end + + function set_properties(obj,vgin,propNames) + %SET_PROPERTIES Parse varargin input to set object properties + % + % IOSR.DSP.AUDIO.SET_PROPERTIES(VGIN,PROPNAMES) searches through + % the cell array VGIN (a cell array of parameter/value pairs) for + % properties specified in the cell array PROPNAMES. Any matching + % properties are written to OBJ. + + % count arguments + nArgs = length(vgin); + if round(nArgs/2)~=nArgs/2 + error('iosr:audio:nameValuePair',[class(obj) ' needs propertyName/propertyValue pairs']) + end + % overwrite defults + for pair = reshape(vgin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},propNames); % find match parameter names + if any(IX) + % do the overwrite + obj.(propNames{IX}) = pair{2}; + else + error('iosr:audio:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + + end + + function cpObj = copyElement(obj) + %COPYELEMENT Overload copy method with additional functionality + + % Make a shallow copy of all properties + cpObj = copyElement@matlab.mixin.Copyable(obj); + + end + + end + + methods (Static) + + function [y,gain] = normalize(x) + %NORMALIZE Normalize an audio signal + % + % Y = IOSR.DSP.AUDIO.NORMALIZE(X) normalises X such that + % ABS(Y(:))<1. + % + % [Y,GAIN] = IOSR.DSP.AUDIO.NORMALIZE(X) returns the scalar gain + % GAIN applied to X in order to normalize it. + + gain = (1-((2*16)/(2^16)))/max(abs(x(:))); + y = x.*gain; + + end + + function y = spat(SOFAfile,x,azimuth,elevation,fs) + %SPAT Spatialise a sound using a SOFA file + % + % IOSR.DSP.AUDIO.SPAT(SOFAFILE,X,AZIMUTH,ELEVATION) spatialises + % the signal X using spatialisation data contained in the SOFA + % file SOFAFILE at the corresponding AZIMUTH and ELEVATION. The + % sampling frequency is that of the SOFA data. X should be a + % column vector; if it is not, it will be down-mixed to a column + % vector. + % + % IOSR.DSP.AUDIO.SPAT(...,FS) uses the sampling frequency FS for + % the spatialisation. If the SOFA data are not at the sampling + % rate FS, the data are resampled. + + assert(size(x,1)>1, 'iosr:audio:invalidX', 'X should be a column vector. Matrices will be downmixed to a column vector'); + + if size(x,2)>1 % mix to mono + x = audio.up_down_mix(x,1); + end + SOFAobj = SOFAload(SOFAfile); % load SOFA object + if ~exist('fs','var')==1 % set default FS + fs = SOFAobj.Data.SamplingRate; + end + + % convert navigational coordinates to spherical coordinates + if azimuth<0 + [azimuth,elevation] = nav2sph(azimuth,elevation); + end + + % find index of corresponding IR is SOFA obj + dist = (SOFAobj.SourcePosition(:,1)-azimuth).^2 + ... + (SOFAobj.SourcePosition(:,2)-elevation).^2; + [~,idx] = min(dist); + + % return IR + IR = squeeze(SOFAobj.Data.IR(idx,:,:))'; + + % resample? + if SOFAobj.Data.SamplingRate~=fs + disp(['Resampling audio to ' num2str(fs) ' Hz.']) + IR = resample(IR,fs,SOFAobj.Data.SamplingRate); + end + + % convolve + y = zeros(length(x)+size(IR,1)-1,size(IR,2)); + for c = 1:size(IR,2) + y(:,c) = iosr.dsp.convFft(x,IR(:,c)); + end + + % crop + y = y(1:length(x),:); + + end + + function y = up_down_mix(x,N) + %UP_DOWN_MIX Remix a source to a designated channel count + % + % Y = IOSR.DSP.AUDIO.UP_DOWN_MIX(X,N) mixes the signal X to have + % the specified channel count N. Data for each channel in X + % should be stored down its columns. For input channel count M, + % the up-/down-mix coefficients are calculated as + % ONES(M,N)./(M*N). + + M = size(x,2); + y = x*(ones(M,N)./(M*N)); + + end + + end + + methods (Static, Access = protected) + + function ensure_path(filename) + %ENSURE_PATH Ensure path exists for specified filename + + % get path + filepath = fileparts(filename); + if ~isempty(filepath) + % ensure path exits + if exist(filepath,'dir')~=7 + mkdir(filepath) + end + end + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/autocorr.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/autocorr.m new file mode 100644 index 0000000000000000000000000000000000000000..32540d1df5908c46320fd621686d439f156242e3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/autocorr.m @@ -0,0 +1,35 @@ +function a = autocorr(x,Q,dim) +%AUTOCORR Perform autocorrelation via FFT +% +% IOSR.DSP.AUTOCORR(X) performs autocorrelation via FFT on vector X. For +% matrices, the autocorrelation is performed on each column. For N-D +% arrays, the autocorrelation is performed on the first non-singleton +% dimension. +% +% IOSR.DSP.AUTOCORR(X,Q) allows the sharpness of the autocorrelation to +% be controlled. Q=2 will give a true autocorrelation; smaller values +% will lead to sharper peaks. +% +% IOSR.DSP.AUTOCORR(X,[],DIM) or autocorr(X,Q,DIM) performs the +% autocorrelation along the dimension DIM. +% +% See also XCORR. + +% Copyright 2016 University of Surrey. + + if nargin < 2 || isempty(Q) + Q = 2; + end + + if nargin < 3 + nsdim = find(size(x)>1,1,'first'); + if isempty(nsdim) + dim = 1; + else + dim = nsdim; + end + end + + a = ifft(abs(fft(x,[],dim)).^Q,[],dim); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/convFft.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/convFft.m new file mode 100644 index 0000000000000000000000000000000000000000..6c0f2239a33737991f771500490b32ad8570c867 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/convFft.m @@ -0,0 +1,83 @@ +function c = convFft(a,b,shape) +%CONVFFT Convolve two vectors using FFT multiplication +% +% Convolution using traditional overlapping methods can be slow for very +% long signals. A more efficient method is to multiply the FFTs of the +% signals and take the inverse FFT of the result. However, this comes at +% a cost: FFT-based convolution is subject to floating-point round-off +% errors, and requires more memory [1]. +% +% C = IOSR.DSP.CONVFFT(A,B) convolves vectors A and B. The resulting +% vector is length: length(A)+length(B)-1. +% +% C = IOSR.DSP.CONVFFT(A,B,SHAPE) returns a subsection of the convolution +% with size specified by SHAPE: +% 'full' - (default) returns the full convolution, +% 'same' - returns the central part of the convolution that is the +% same size as a. +% 'valid' - returns only those parts of the convolution that are +% computed without the zero-padded edges. length(c) is +% L-2*(min(P,Q)-1) where P = numel(a), Q = numel(b), +% L = P+Q-1. +% +% Based on code written by Steve Eddins, 2009. +% +% References +% +% [1] http://blogs.mathworks.com/steve/2009/11/03/ +% the-conv-function-and-implementation-tradeoffs/ +% +% See also CONV. + +% Copyright 2016 University of Surrey. + + assert(isvector(a) & isvector(b), 'iosr:convFft:invalidInput', 'a and b must be vectors') + + if nargin<3 + shape = 'full'; + end + assert(ischar(shape), 'iosr:convFft:invalidShape', 'Unknown shape parameter') + + P = numel(a); + Q = numel(b); + L = P + Q - 1; + K = 2^nextpow2(L); + + % do the convolution + afft = fft(a, K); + bfft = fft(b, K); + c = ifft(afft(:).*bfft(:)); + + % specify index range for shape + switch lower(shape) + case 'full' + range = [1, L]; + case 'same' + range = [floor(length(b)/2)+1, L-ceil(length(b)/2)+1]; + case 'valid' + range = [min(P,Q), L-min(P,Q)+1]; + otherwise + error('iosr:convFft:unknownShape',['shape ''' shape ''' is invalid. The options are ''full'' (default), ''same'', or ''valid''.']) + end + + % crop to shape + c = c(range(1):range(2)); + + % restore orientation + if shape(1) == 'f' + if length(a) > length(b) + if size(a,1) == 1 %row vector + c = c.'; + end + else + if size(b,1) == 1 %row vector + c = c.'; + end + end + else + if size(a,1) == 1 %row vector + c = c.'; + end + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/istft.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/istft.m new file mode 100644 index 0000000000000000000000000000000000000000..c033ee0a73b6683521a94cf851ec2e58352374fe --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/istft.m @@ -0,0 +1,88 @@ +function [x,t] = istft(s,nfft,hop,fs) +%ISTFT Calculate the Inverse Short-Time Fourier Transform +% +% X = IOSR.DSP.ISTFT(S) calculates the inverse short-time Fourier +% transform (ISTFT), from the 1024-point one-sided FFTs in each column of +% S, using the overlap-add method. It is assumed that FFTs are calculated +% in steps of HOP=512. X is a column vector of length (HOP*K)+(NFFT-HOP) +% where K is SIZE(X,2). +% +% X = IOSR.DSP.ISTFT(S,NFFT) uses FFT-length NFFT and HOP=FIX(NFFT/2). +% +% X = IOSR.DSP.ISTFT(S,NFFT,HOP) uses the hop size HOP. +% +% [X,T] = IOSR.DSP.ISTFT(S,NFFT,HOP,FS) returns the corresponding time T +% (seconds) for each element of X based on sampling frequency FS. +% +% Example +% +% % create a spectrogram using a Hann window +% % and convert back to the time domain +% load handel.mat +% nfft = 1024; +% hop = 128; +% Y = iosr.dsp.stft(y,hann(nfft),hop); +% z = iosr.dsp.istft(Y,nfft,hop); +% +% See also IOSR.DSP.STFT. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(ismatrix(s), 'iosr:istft:invalidS', 'S must be a matrix') + + % check nfft + if nargin<2 + nfft = 1024; + else + assert(isscalar(nfft) && round(nfft)==nfft && nfft>0, 'iosr:istft:invalidNfft', 'NFFT must be a positive scalar integer') + end + + % determine hop size + if nargin<3 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:istft:invalidHop', 'hop must be an integer') + assert(hop<=nfft && hop>0, 'iosr:istft:invalidHop', 'hop must be less than or equal to nfft, and greater than 0') + end + + % determine fs + if nargin<4 + fs = 1; + else + assert(isscalar(fs), 'iosr:istft:invalidFs', 'FS must be an scalar') + end + + %% calculate outputs + + % calculate number of frames and samples + K = size(s,2); + M = (hop*K)+(nfft-hop); + + % calculate highest bin and correction for one-sided FFT + if mod(nfft,2)==0 + Nout = (nfft/2)+1; + ec = 1; + else + Nout = (nfft+1)/2; + ec = 0; + end + + % check FFT size + assert(size(s,1)==Nout, 'iosr:istft:invalidS', sprintf('SIZE(S,1) is not correct for an FFT-length of %d',nfft)) + + % calculate ISTFTs + x = zeros(M,1); + for k = 1:K + samples = ((k-1)*hop)+1:((k-1)*hop)+nfft; + Xtemp = [s(:,k); conj(s(end-ec:-1:2,k))]; + x(samples) = x(samples)+ifft(Xtemp); + end + + % calculate time + if nargout>1 + t = (0:M-1)./fs; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/lapwin.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/lapwin.m new file mode 100644 index 0000000000000000000000000000000000000000..c151d7fd60900109d58dc24d452b5e98d560bcee --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/lapwin.m @@ -0,0 +1,28 @@ +function w = lapwin(L,b) +%LAPWIN Laplace window. +% +% IOSR.DSP.LAPWIN(N) returns an N-point Laplace window. The window w(x) is +% calculated for -10<=x<=10. +% +% IOSR.DSP.LAPWIN(N,B) returns an N-point Laplace window using scale parameter B. +% If omitted, B is 2. +% +% See also GAUSSWIN, CHEBWIN, KAISER, TUKEYWIN, WINDOW. + +% Copyright 2016 University of Surrey. + + assert(isscalar(L) && round(L)==L, 'iosr:lapwin:invalidL', 'L must be a scalar and whole number.') + + if nargin<2 + b = 2; + else + assert(isscalar(b), 'iosr:lapwin:invalidB', 'b must be a scalar.') + end + + w = zeros(L,1); + N = L-1; + x = 10.*((0:N)'-N/2)./(N/2); + w(x<0) = exp(-(-x(x<0)./b)); + w(x>=0) = exp(-(x(x>=0)./b)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/localpeaks.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/localpeaks.m new file mode 100644 index 0000000000000000000000000000000000000000..bd261c04402b864b6bfb4d7d346845a957aff4c8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/localpeaks.m @@ -0,0 +1,42 @@ +function peaks = localpeaks(x,mode) +%LOCALPEAKS Find local peaks and troughs in a vector +% +% This function returns the indices of local peaks and/or troughs in a +% vector. +% +% PEAKS = IOSR.DSP.LOCALPEAKS(X) locates the local peaks in vector X. +% +% PEAKS = IOSR.DSP.LOCALPEAKS(X,MODE) locates local features specified by +% mode, which can be set to 'peaks' (default), 'troughs' in order to +% identify local troughs, or 'both' in order to identify both local peaks +% and troughs. + +% Copyright 2016 University of Surrey. + + assert(isvector(x), 'iosr:localpeaks:invalidX', 'Input must be a vector') + + if nargin < 2 + mode = 'peaks'; + end + + switch lower(mode) + case 'peaks' + % do nothing + peaks = find_peaks(x); + case 'troughs' + peaks = find_peaks(-x); + case 'both' + peaks = find_peaks(x) | find_peaks(-x); + otherwise + error('iosr:localpeaks:unknownMode','Unknown localpeak mode. Please specify ''peaks'', ''troughs'' or ''both'''); + end + +end + +function peaks = find_peaks(x) +%FIND_PEAKS find local peaks in a vector + + peaks = false(size(x)); + peaks(2:end-1) = sign(x(2:end-1)-x(1:end-2)) + sign(x(2:end-1)-x(3:end)) > 1; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/ltas.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/ltas.m new file mode 100644 index 0000000000000000000000000000000000000000..838cb2627d9564da23808b9239a099a2c14c21ef --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/ltas.m @@ -0,0 +1,219 @@ +function [s,f] = ltas(x,fs,varargin) +%LTAS calculate the long-term average spectrum of a signal +% +% S = IOSR.DSP.LTAS(X,FS) calculates the long-term average spectrum +% (LTAS) of signal X, sampled at FS Hz. The spectrum is calculated from +% the average power spectral density (PSD) obtained from a series of +% overlapping FFTs; the FFT length is 4096, and the hop size is 2048. The +% segments of X are Hann-windowed. The average PSD is then +% Gaussian-smoothed to 1/3-octave resolution. +% +% X can be a vector, matrix, or multidimensional array; LTAS will operate +% along the first non-signleton dimension, and return the LTAS for each +% corresponding row/column/etc. +% +% S = IOSR.DSP.LTAS(X,FS,'PARAMETER','VALUE') allows numerous parameters +% to be specified. These parameters are:- +% 'dim' : {find(size(X)>1,1,'first')} | scalar +% Specifies the dimension of operation (defaults to the first +% non-singleton dimension). +% 'graph' : {false} | true +% Choose whether to plot a graph of the LTAS. +% 'hop' : {NFFT/2} | scalar +% Specifies the step size through X used to calculate each +% segment. NFFT is determined by the 'win' parameter. +% 'noct' : {3} | scalar +% Apply 1/noct-octave smoothing to the frequency spectrum. +% Setting 'noct' to 0 results in no smoothing. +% 'scaling' : {'none'} | 'max0' +% Specifies any scaling to apply to S. By default, no scaling is +% applied. If scaling is set to 'max0', S will be scaled to have +% a maximum value of 0dB. +% 'units' : {dB} | 'none' +% Specifies the output units. By default the PSD is calculated in +% dB. Otherwise the PSD is returned directly. +% 'win' : {4096} | scalar | vector +% Specifies the window or FFT length NFFT used to calculate the +% spectrum. If 'win' is a scalar, it specifies the FFT length, +% and a Hann window is applied to each segment. If 'win' is a +% vector, NFFT is the length of the vector, and the vector is +% multiplied with each segment. +% +% [S,F] = IOSR.DSP.LTAS(...) returns the frequencies F for each +% corresponding bin of S. +% +% Example +% +% % Plot the 1/6th-octave-smoothed LTAS of the Handel example +% load handel.mat +% figure +% iosr.dsp.ltas(y,Fs,'noct',6,'graph',true); +% +% See also IOSR.DSP.STFT, IOSR.DSP.SMOOTHSPECTRUM. + +% Copyright 2016 University of Surrey. + + %% parse input + + if nargin < 2 + error('iosr:ltas:nargin''Not enough input arguments') + end + + options = struct(... + 'win',4096,... + 'hop',[],... + 'noct',3,... + 'dim',[],... + 'units','db',... + 'scaling','none',... + 'graph',false); + + % read parameter/value inputs + if nargin>2 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:ltas:nameValuePair','LTAS needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:ltas:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + %% check and assign input + + % required inputs + assert(isnumeric(x), 'iosr:ltas:invalidX', 'X must be numeric.'); + assert(isscalar(fs), 'iosr:ltas:invalidFs', 'FS must be a scalar.'); + assert(fs>0, 'iosr:ltas:invalidFs', 'FS must be greater than 0.'); + assert(isint(fs), 'iosr:ltas:invalidFs', 'FS must be an integer.'); + + % determine fft parameters + if numel(options.win)>1 && isvector(options.win) + NFFT = length(options.win); + win = options.win; + elseif isscalar(options.win) + NFFT = options.win; + win = NFFT; + else + error('iosr:ltas:invalidWin','''WIN'' must be a vector or a scalar'); + end + assert(isint(NFFT) && NFFT>0, 'iosr:ltas:invalidNfft', '''WIN'' must be a positive integer'); + + % determine hop + hop = options.hop; + if isempty(hop) + hop = fix(NFFT/2); + end + + % smoothing + Noct = options.noct; + + % dimension to operate along + dim = options.dim; + dims = size(x); + if isempty(dim) + dim = find(dims>1,1,'first'); + else + assert(isnumeric(dim),'iosr:ltas:invalidDim', 'DIM must be an integer'); + assert(isint(dim), 'iosr:ltas:invalidDim', 'DIM must be an integer or empty'); + assert(dim>0, 'iosr:ltas:invalidDim', 'DIM must be greater than 0') + end + + %% permute and rehape x to operate down columns + + % number of useful coefficients + if mod(NFFT,2)==0 + Nout = (NFFT/2)+1; + else + Nout = (NFFT+1)/2; + end + + % reorder and permute + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x = rearrange(x,order,[dims_shift(1) prod(dims_shift(2:end))]); + dims_out_shift = dims_shift; + dims_out_shift(1) = Nout; + + %% calculate spectra + + % choose units function + switch lower(options.units) + case 'db' + units = @(x) 10*log10(x); + max0scale = @(s) s-max(s(:)); + labelY = 'Power spectral density [dBFS]'; + yscale = 'linear'; + case 'none' + units = @(x) x; + max0scale = @(s) s./max(s(:)); + labelY = 'Power spectral density'; + yscale = 'log'; + otherwise + error('iosr:ltas:unknownUnits','Unknown units option ''%s''',options.units); + end + + % do calculations + s = zeros(dims_out_shift); + for c = 1:size(x,2) + [S,f] = iosr.dsp.stft(x(:,c),win,hop,fs); % short-time ft + s(:,c) = mean(abs(S/NFFT).^2,2); % mean PSD + s(:,c) = units(s(:,c)); % put into dB + s(:,c) = iosr.dsp.smoothSpectrum(s(:,c),f,Noct); % smooth + end + + % invert permutation + s = irearrange(s,order,dims_out_shift); + + % scale output + switch lower(options.scaling) + case 'max0' + s = max0scale(s); + case 'none' + % do nothing + otherwise + error('iosr:matchEQ:unknownScaling','Unknown scaling option ''%s''',options.scaling); + end + + %% plot + + assert(islogical(options.graph) && numel(options.graph)==1, 'iosr:ltas:invalidGraph', '''graph'' option must be logical.') + if options.graph + semilogx(f,rearrange(s,order,[dims_out_shift(1) prod(dims_out_shift(2:end))])); + xlabel('Frequency [Hz]'); + ylabel(labelY); + set(gca,'yscale',yscale); + grid on + if prod(dims_out_shift(2:end)) > 1 + legend(num2str((1:prod(dims_out_shift(2:end)))')); + end + end + +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end + +function y = isint(x) +%ISINT check if input is whole number + y = x==round(x); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/matchEQ.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/matchEQ.m new file mode 100644 index 0000000000000000000000000000000000000000..f2ff913dea2b4521f097e7b523350ccf1452bad1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/matchEQ.m @@ -0,0 +1,223 @@ +function [y,b] = matchEQ(x,fs,mag,f,varargin) +%MATCHEQ Match the LTAS of a signal to an arbitrary spectral magnitude +% +% Y = IOSR.DSP.MATCHEQ(X,FS,MAG,F) matches the long-term average spectrum +% of X, sampled at FS Hz, to the spectral magnitudes contained in vector +% MAG sampled at frequencies in vector F. X can be a vector, matrix, or +% multidimensional array; MATCHEQ will operate along the first +% non-signleton dimension. Y is the same size as X. +% +% Y = IOSR.DSP.MATCHEQ(X,FS,MAG,F,'PARAMETER','VALUE') allows numerous +% parameters to be specified. These parameters are:- +% 'dim' : {find(size(X)>1,1,'first')} | scalar +% Specifies the dimension of operation (defaults to the first +% non-singleton dimension). +% 'boostRatio' : {1} | scalar +% Determine the correction ratio for spectral regions that are +% amplified. By default, the 'ratio' parameter is used. See +% 'ratio' below. +% 'cutRatio' : {1} | scalar +% Determine the correction ratio for spectral regions that are +% attenuated. By default, the 'ratio' parameter is used. See +% 'ratio' below. +% 'hop' : {NFFT/2} | scalar +% Specifies the step size through X used to calculate each +% segment for the LTAS. NFFT is determined by the 'win' +% parameter. +% 'ltasNorm' : {'none'} | 'peak' | 'sum' +% Apply normalisation to the LTAS. By default, no normalisation +% is applied, and the equalisation will attempt to match the +% targtet magnitude. By setting the normalisation to 'peak', MAG +% and the LTAS of X are normalised in order to have a peak gain +% of unity before calculating the correction filter. By setting +% the normalisation to 'sum', MAG and the LTAS of X are +% normalised in order to sum to unity before calculating the +% correction filter. +% 'noct' : {3} | scalar +% Apply 1/noct-octave smoothing to the LTAS. Setting 'noct' to 0 +% results in no smoothing. +% 'order' : {2048} | scalar +% Determine the order of the correction filter. +% 'ratio' : {1} | scalar +% Determine the correction ratio. A value of 0 means that no +% correction is applied; 1 means that the full correction is +% applied; a value greater than 1 will over-correct. +% 'win' : {4096} | scalar | vector +% Specifies the window or FFT length NFFT used to calculate the +% LTAS. If 'win' is a scalar, it specifies the FFT length, +% and a Hann window is applied to each segment. If 'win' is a +% vector, NFFT is the length of the vector, and the vector is +% multiplied with each segment. +% +% [Y,B] = IOSR.DSP.MATCHEQ(...) returns the filter coefficients to the +% array B. B is the same size as X, except that the DIMth dimension of B +% has length N+1, where N is the filter order and DIM is the dimension of +% operation. +% +% Example +% +% % flatten the spectrum of the Handel example +% load handel.mat +% f = linspace(0,1,1024); +% mag = ones(size(f)); +% z = iosr.dsp.matchEQ(y,Fs,mag,f,'ltasNorm','sum'); +% +% See also IOSR.DSP.LTAS. + +% Copyright 2016 University of Surrey. + + %% parse input + + if nargin < 4 + error('iosr:matchEQ:nargin','Not enough input arguments') + end + + options = struct(... + 'win',4096,... + 'hop',[],... + 'noct',3,... + 'dim',[],... + 'ratio',1,... + 'boostRatio',[],... + 'cutRatio',[],... + 'order',2048,... + 'ltasNorm','none'); + + % read parameter/value inputs + if nargin>4 % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(varargin); + if round(nArgs/2)~=nArgs/2 + error('iosr:matchEQ:nameValuePair','MATCHEQ needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(varargin,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:matchEQ:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + %% check and assign input + + % required inputs + assert(isnumeric(x), 'iosr:matchEQ:invalidX', 'X must be numeric.'); + assert(isscalar(fs), 'iosr:matchEQ:invalidFs', 'FS must be a scalar.'); + assert(fs>0, 'iosr:matchEQ:invalidFs', 'FS must be greater than 0.'); + assert(isint(fs), 'iosr:matchEQ:invalidFs', 'FS must be an integer.'); + assert(isnumeric(mag) && isvector(mag), 'iosr:matchEQ:invalidMag', 'MAG must be a numeric vector.') + assert(isnumeric(f) && isvector(f), 'iosr:matchEQ:invalidF', 'F must be a numeric vector.') + assert(isequal(size(mag),size(f)), 'iosr:matchEQ:invalidInputs', 'F and MAG must be the same size.') + assert(all(f>=0), 'iosr:matchEQ:invalidF', 'Frequencies in F must be greater than or equal to 0.') + assert(all(mag>=0), 'iosr:matchEQ:invalidMag', 'Magnitudes in MAG must be greater than or equal to 0.') + + % dimension to operate along + dim = options.dim; + dims = size(x); + if isempty(dim) + dim = find(dims>1,1,'first'); + else + assert(isnumeric(dim), 'iosr:matchEQ:invalidDim', 'DIM must be an integer'); + assert(isint(dim), 'iosr:matchEQ:invalidDim', 'DIM must be an integer or empty'); + assert(dim>0, 'iosr:matchEQ:invalidDim', 'DIM must be greater than 0') + end + + f = f(:); + mag = mag(:); + + %% Determine ratios + + assert(options.ratio>=0 && isscalar(options.ratio), 'iosr:matchEQ:invalidRatio', 'Ratio must be a positive scalar.') + + if isempty(options.boostRatio) + boostRatio = options.ratio; + else + boostRatio = options.boostRatio; + end + + if isempty(options.cutRatio) + cutRatio = options.ratio; + else + cutRatio = options.cutRatio; + end + + assert(boostRatio>=0 && isscalar(boostRatio), 'iosr:matchEQ:invalidBoostRatio', 'BoostRatio must be a positive scalar.') + assert(cutRatio>=0 && isscalar(cutRatio), 'iosr:matchEQ:invalidCutRatio', 'CutRatio must be a positive scalar.') + + %% Determine normalisation + + switch lower(options.ltasNorm) + case 'none' + fltas = @(x) x; + case 'sum' + fltas = @(x) x./sum(x); + case 'peak' + fltas = @(x) x./max(x); + otherwise + error('iosr:matchEQ:unknownNorm','Unknown normalisation mode ''%s''',options.ltasNorm) + end + + %% permute and rehape x to operate down columns + + % reorder and permute + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x = rearrange(x,order,[dims_shift(1) prod(dims_shift(2:end))]); + dims_out_shift = dims_shift; + b_out_dims = dims_shift; b_out_dims(1) = options.order+1; + + %% EQ + + assert(isscalar(options.order) && options.order>0 && isint(options.order),... + 'iosr:matchEQ:invalidOrder', ... + 'ORDER must be a positive scalar integer.') + + % do calculations + y = zeros(size(x)); + b = zeros(b_out_dims); + for c = 1:size(x,2) + [mX,fX] = iosr.dsp.ltas(x(:,c),fs,... + 'hop',options.hop,... + 'noct',options.noct,... + 'win',options.win,... + 'units','none'); + mX = fltas(mX); + if ~isequal(fX(:),f) + mag = interp1(f,mag,fX,'spline','extrap'); + end + mag = fltas(mag); + matcher = sqrt(mag./mX); + matcher(matcher>1) = matcher(matcher>1).*boostRatio; + matcher(matcher<1) = matcher(matcher<1).*cutRatio; + b(:,c) = fir2(options.order,2.*fX./fs,matcher); + y(:,c) = filter(b(:,c),1,x(:,c)); + end + + % invert permutation + y = irearrange(y,order,dims_out_shift); + b = irearrange(b,order,b_out_dims); + +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end + +function y = isint(x) +%ISINT check if input is whole number + y = x==round(x); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/rcoswin.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/rcoswin.m new file mode 100644 index 0000000000000000000000000000000000000000..bf6dbc77b9e217b69f4b96c711f670b798f56902 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/rcoswin.m @@ -0,0 +1,23 @@ +function w = rcoswin(N) +%RCOSWIN Raised cosine window. +% +% IOSR.DSP.RCOSWIN(N) returns an N-point raised cosine window. +% +% See also GAUSSWIN, CHEBWIN, KAISER, TUKEYWIN, WINDOW. + +% Copyright 2016 University of Surrey. + + assert(isscalar(N) && round(N)==N, 'iosr:rcoswin:invalidN', 'N must be a scalar and whole number.') + assert(N > 0, 'iosr:rcoswin:invalidN', 'N must be greater than 0.') + + switch N + case 1 + w = 1; + case 2 + w = [.5; .5]; + otherwise + r = linspace(-pi,pi,N)'; + w = (cos(r)+1)/2; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/rms.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/rms.m new file mode 100644 index 0000000000000000000000000000000000000000..3b75a4fb31430a9144276b956a55d6a1e3ecf004 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/rms.m @@ -0,0 +1,22 @@ +function rms = rms(x,dim) +%RMS Calculate the rms of a vector or matrix +% +% RMS = IOSR.DSP.RMS(X) calculates the Root Mean Square of X along the +% first non-singleton dimension of vector or matrix X. For vectors, +% IOSR.DSP.RMS(X) is the RMS value of the elements in x. For matrices, +% IOSR.DSP.RMS(X) is a row vector containing the RMS value of each +% column. For N-D arrays, IOSR.DSP.RMS(X) is the RMS value of the +% elements along the first non-singleton dimension of X. +% +% RMS = IOSR.DSP.RMS(X,DIM) calculates the RMS of X along the dimension +% DIM. + +% Copyright 2016 University of Surrey. + + if nargin == 1 + dim = find(size(x)~=1,1,'first'); + end + + rms = sqrt(mean(x.^2,dim)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/sincFilter.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/sincFilter.m new file mode 100644 index 0000000000000000000000000000000000000000..ee7b5bfc09aaff6e389dec884f781c0a18e23c2f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/sincFilter.m @@ -0,0 +1,102 @@ +function y = sincFilter(x,Wn,N,dim) +%SINCFILTER Apply a near-ideal low-pass or band-pass brickwall filter +% +% Y = IOSR.DSP.SINCFILTER(X,WN) applies a near-ideal low-pass or +% band-pass brickwall filter to the array X, operating along the first +% non-singleton dimension (e.g. down the columns of a matrix). The +% cutoff frequency/frequencies are specified in WN. If WN is a scalar, +% then WN specifies the low-pass cutoff frequency. If WN is a two-element +% vector, then WN specifies the band-pass interval. WN must be 0.0 < WN < +% 1.0, with 1.0 corresponding to half the sample rate. +% +% The filtering is performed by FFT-based convolution of X with the sinc +% kernel. +% +% Y = IOSR.DSP.SINCFILTER(X,WN,N) allows the filter length to be +% specified. The default value is N=1025. The filter length is doubled in +% the band-pass case. In either case, if N is even the final filter +% length will be N+1. +% +% Y = IOSR.DSP.SINCFILTER(X,WN,N,DIM) applies the specified filter along +% the dimension DIM. +% +% Y = IOSR.DSP.SINCFILTER(X,WN,[],DIM) applies the specified filter along +% the dimension dim using the default filter length. +% +% See also IOSR.DSP.CONVFFT. + +% Copyright 2016 University of Surrey. + + %% test input + + assert(nargin>=2, 'iosr:sincFilter:nargin', 'Not enough input arguments') + assert((numel(Wn)==1 || numel(Wn)==2) & isnumeric(Wn), 'iosr:sincFilter:invalidWn', 'Wn must be a scalar or two-element vector.') + assert(isnumeric(x), 'iosr:sincFilter:invalidX', 'x must be a numeric array.') + assert(all(Wn<=1) & all(Wn>=0), 'iosr:sincFilter:invalidWn', 'Wn must be 0.0 < Wn < 1.0, with 1.0 corresponding to half the sample rate.') + dims = size(x); + if nargin<4 + dim = []; + else + assert(isint(dim) & numel(dim)==1, 'iosr:sincFilter:invalidDim', 'dim must be an integer') + assert(dim<=length(dims), 'iosr:sincFilter:invalidDim', 'dim must be less than or equal to the number of dimensions in x') + end + if nargin<3 + N = []; + elseif ~isempty(N) + assert(isscalar(N) & isint(N), 'iosr:sincFilter:invalidN', 'N must be an integer scalar.') + end + + %% assign defaults + + if isempty(N) + N = 1025; + end + if isempty(dim) + dim = find(dims>1,1,'first'); + end + + %% reshape input to matrix with requested dim made as first dimension + + % reshape data so function works down columns + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + x = permute(x,order); + dims_shift = dims(order); + x = reshape(x,dims_shift(1),numel(x)/dims_shift(1)); + y = zeros(size(x)); + + %% create filter kernel + + if numel(Wn)==1 % low-pass + n = -floor(N/2):floor(N/2); % create time base + B = sinc_kernel(Wn,n); % make kernel + else % band-pass + n = -N:N; % create time base + B = sinc_kernel(Wn(2),n)-sinc_kernel(Wn(1),n); % make kernel + end + + %% apply filter + + for N = 1:size(y,2) + y(:,N) = iosr.dsp.convFft(x(:,N),B,'same'); + end + + %% reshape out to match input + + y = reshape(y,dims_shift); + y = ipermute(y,order); + +end + +function k = sinc_kernel(Wn,n) +% SINC_KERNEL Make sinc kernel + + k = sinc(Wn*n).*Wn; + +end + +function y = isint(x) +% ISINT Test whether x is integer value (not type) + + y = x==round(x); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/smoothSpectrum.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/smoothSpectrum.m new file mode 100644 index 0000000000000000000000000000000000000000..6717ffa9c3ca1f5124d21c7b26624f52ec002dc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/smoothSpectrum.m @@ -0,0 +1,92 @@ +function x_oct = smoothSpectrum(X,f,Noct) +%SMOOTHSPECTRUM Apply 1/N-octave smoothing to a frequency spectrum +% +% X_OCT = IOSR.DSP.SMOOTHSPECTRUM(X,F,NOCT) applies 1/NOCT-octave +% smoothing to the frequency spectrum contained in vector X sampled at +% frequencies in vector F. X can be a log-, magnitude-, or +% power-spectrum. Setting Noct to 0 results in no smoothing. +% +% Algorithm +% +% The function calculates the i-th smoothed spectral coefficient X_OCT(i) +% as the sum of the windowed spectrum. The window is a Gaussian whose +% centre frequency is F(i), and whose standard deviation is proportional +% to F(i)/NOCT. +% +% Example +% +% % Calculate the 1/3-octave-smoothed power spectral density of the +% % Handel example. +% +% % load signal +% load handel.mat +% +% % take fft +% Y = fft(y); +% +% % keep only meaningful frequencies +% NFFT = length(y); +% if mod(NFFT,2)==0 +% Nout = (NFFT/2)+1; +% else +% Nout = (NFFT+1)/2; +% end +% Y = Y(1:Nout); +% f = ((0:Nout-1)'./NFFT).*Fs; +% +% % put into dB +% Y = 20*log10(abs(Y)./NFFT); +% +% % smooth +% Noct = 3; +% Z = iosr.dsp.smoothSpectrum(Y,f,Noct); +% +% % plot +% figure +% semilogx(f,Y,f,Z) +% grid on +% +% See also IOSR.DSP.LTAS, FFT. + +% Copyright 2016 University of Surrey. + + %% Input checking + + assert(isvector(X), 'iosr:smoothSpectrum:invalidX', 'X must be a vector.'); + assert(isvector(f), 'iosr:smoothSpectrum:invalidF', 'F must be a vector.'); + assert(isscalar(Noct), 'iosr:smoothSpectrum:invalidNoct', 'NOCT must be a scalar.'); + assert(isreal(X), 'iosr:smoothSpectrum:invalidX', 'X must be real.'); + assert(all(f>=0), 'iosr:smoothSpectrum:invalidF', 'F must contain positive values.'); + assert(Noct>=0, 'iosr:smoothSpectrum:invalidNoct', 'NOCT must be greater than or equal to 0.'); + assert(isequal(size(X),size(f)), 'iosr:smoothSpectrum:invalidInput', 'X and F must be the same size.'); + + %% Smoothing + + % calculates a Gaussian function for each frequency, deriving a + % bandwidth for that frequency + + x_oct = X; % initial spectrum + if Noct > 0 % don't bother if no smoothing + for i = find(f>0,1,'first'):length(f) + g = gauss_f(f,f(i),Noct); + x_oct(i) = sum(g.*X); % calculate smoothed spectral coefficient + end + % remove undershoot when X is positive + if all(X>=0) + x_oct(x_oct<0) = 0; + end + end + +end + +function g = gauss_f(f_x,F,Noct) +% GAUSS_F calculate frequency-domain Gaussian with unity gain +% +% G = GAUSS_F(F_X,F,NOCT) calculates a frequency-domain Gaussian function +% for frequencies F_X, with centre frequency F and bandwidth F/NOCT. + + sigma = (F/Noct)/pi; % standard deviation + g = exp(-(((f_x-F).^2)./(2.*(sigma^2)))); % Gaussian + g = g./sum(g); % normalise magnitude + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/stft.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/stft.m new file mode 100644 index 0000000000000000000000000000000000000000..3cf2e508315cb62c77aa887798d579303db0de1a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/stft.m @@ -0,0 +1,119 @@ +function [s,f,t] = stft(x,nfft,hop,fs) +%STFT Calculate the short-time Fourier transform of a signal +% +% S = IOSR.DSP.STFT(X) calculates the short-time Fourier transform (STFT) +% of signal X using 1024-point segments in steps (hops) of 512 points. S +% is a series of one-sided FFTs of size [N,K] where N is the number of +% frequency bins and K is the number of time frames, such that N=513 and +% K=FIX((LENGTH(X)-512)/512). A hamming window is applied to each time +% segment. The window is normalised such that it fulfills the constant +% overlap-add (COLA) criterion. Fulfilling the criterion is useful when +% resynthesising the signal using the ISTFT, as the magnitude of the +% output of the ISTFT will be retained. +% +% S = IOSR.DSP.STFT(X,NFFT) calculates the STFT using NFFT-point +% segments. The hop size is HOP=FIX(NFFT/2); +% K=FIX((LENGTH(X)-(NFFT-HOP))/HOP), and N depends on whether NFFT is odd +% or even. If NFFT is even, N=(NFFT/2)+1; if NFFT is odd, N=(NFFT+1)/2. +% +% S = IOSR.DSP.STFT(X,WINDOW) calculates the STFT with +% NFFT=LENGTH(WINDOW) and applies the vector WINDOW to each segment. The +% window is normalised such that it fulfills the constant overlap-add +% (COLA) criterion. The normalised window is calculated as +% HOP.*WINDOW./SUM(WINDOW). +% +% S = IOSR.DSP.STFT(X,WINDOW,HOP) steps through X by HOP samples. +% +% [S,W] = IOSR.DSP.STFT(...) returns the normalised frequencies for each +% bin to W. +% +% [S,F] = IOSR.DSP.STFT(X,WINDOW,HOP,FS) returns the frequencies for each +% bin to F according to sampling frequency FS. +% +% [S,F,T] = IOSR.DSP.STFT(...) returns the corresponding time T (seconds) +% for each column of S. +% +% Example +% +% % plot a spectrogram +% load handel.mat +% [Y,f,t] = iosr.dsp.stft(x,1024,128,Fs); +% figure +% imagesc(t,f,20.*(log10(abs(Y)))); +% set(gca,'ydir','normal') +% ylabel('Frequency [Hz]') +% xlabel('Time [s]') +% +% See also IOSR.DSP.ISTFT. + +% Copyright 2016 University of Surrey. + + %% check input + + assert(isvector(x) && numel(x)>1, 'iosr:stft:invalidX', 'X must be a vector') + + % check nfft + if nargin<2 + nfft = 1024; + end + + % determine window + if numel(nfft)>1 + win = nfft; + assert(isvector(win), 'iosr:stft:invalidNfft', 'WINDOW must be a vector') + nfft = length(win); + else + assert(round(nfft)==nfft && nfft>0, 'iosr:stft:invalidNfft', 'NFFT must be a positive integer') + win = hamming(nfft); + end + + % check x length + assert(length(x)>=nfft, 'iosr:stft:invalidInput', 'X must have at least NFFT samples') + + % determine hop + if nargin<3 + hop = fix(nfft/2); + else + assert(isscalar(hop) & round(hop)==hop, 'iosr:stft:invalidHop', 'HOP must be an integer') + assert(hop<=nfft && hop>0, 'iosr:stft:invalidHop', 'HOP must be less than or equal to NFFT, and greater than 0') + end + + % normalise window + win = hop.*win./sum(win); + + % determine fs + if nargin<4 + fs = 1; + else + assert(isscalar(fs), 'iosr:stft:invaldFs', 'FS must be an scalar') + end + + %% calculate outputs + + % calculate highest bin for one-sided FFT + if mod(nfft,2)==0 + Nout = (nfft/2)+1; + else + Nout = (nfft+1)/2; + end + + % calculate number of frames + K = fix((length(x)-(nfft-hop))/hop); + + % calculate STFTs + s = zeros(Nout,K); + for k = 1:K + samples = ((k-1)*hop)+1:((k-1)*hop)+nfft; + temp = fft(win.*x(samples)); + s(:,k) = temp(1:Nout); + end + + % calculate frequency and time + if nargout>1 + f = fs.*((0:Nout-1)./nfft)'; + end + if nargout>2 + t = (0:K-1).*(hop/fs); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/vsmooth.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/vsmooth.m new file mode 100644 index 0000000000000000000000000000000000000000..085b207eeff5ef165c1f1f08cac9208f9fbbee79 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+dsp/vsmooth.m @@ -0,0 +1,95 @@ +function y = vsmooth(x,frame,mode) +%VSMOOTH Smooth a vector using mathematical functions +% +% Y = IOSR.DSP.VSMOOTH(X,FRAME) smooths the input vector X by calculating +% the running RMS over a series of frames. FRAME specifies the frame +% characteristics; it can be set to: +% +% a scalar - this will be used as the length of the frame, the window +% will be rectangular +% a vector - this specifies the shape of the analysis window, the +% frame length will be length(frame). +% +% Y = IOSR.DSP.VSMOOTH(X,FRAME,MODE) allows the user to specify a +% different mathematical smoothing function in MODE. The options are: +% +% 'rms' - calculates the running rms (default) +% 'mean' - calculates the running mean (moving average filter) +% 'median' - calculates the running median +% +% NOTE: vsmooth uses a vectorized implementation that may be slow when x +% and/or frame are very large. The number of elements that are used for +% calculation is length(X)*max(FRAME,length(FRAME)). The algorithm +% vectorizes the operation by creating a matrix of indexes and extracting +% its diagonals. E.g. for a vector of length 4 and frame_length of 2, the +% algorithm creates a temporary zero-padded matix x2 from which it +% creates a set of indexes: +% +% 1 1 +% 2 2 +% 3 3 +% 4 4 +% 5 5 +% 6 6 +% +% It then extracts the diagonals where -length(x2) + frame_length <= k <= +% 0, yielding: +% +% 1 2 +% 2 3 +% 3 4 +% 4 5 +% +% this is used to index x2; operations are then performed along the rows. + +% Copyright 2016 University of Surrey. + + %% Gather inputs + + assert(isvector(x), 'iosr:vsmooth:vectorInput', '''x'' must be a vector') + + if isscalar(frame) + frame_length = frame; + window = ones(frame_length,1); + elseif isvector(frame) + window = frame; + frame_length = length(frame); + else + error('iosr:vsmooth:frameInvalid','''frame'' must be a vector or a scalar') + end + + if nargin<3 + mode = 'rms'; + end + + %% Smooth + + % zero pad + x2 = [zeros(ceil((frame_length)/2)-1,1); x(:); zeros(floor(frame_length/2),1)]; + + samples = (1:length(x2))'; + samples = samples(:,ones(frame_length,1)); + + % get indexes + index = spdiags(samples,0:-1:-length(x2)+frame_length); + + window2 = window(:,ones(1,length(x))); + + % do calculations + switch lower(mode) + case 'rms' + y = sqrt(mean((window2.*x2(index)).^2)); + case 'median' + y = median((window2.*x2(index))); + case 'mean' + y = mean((window2.*x2(index))); + otherwise + error('iosr:vsmooth:unknownMode','Unknown ''mode'' specified') + end + + % transpose if necessary + if size(y,1)~=size(x,1) + y = y'; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/chMap.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/chMap.m new file mode 100644 index 0000000000000000000000000000000000000000..6c82eb98d471262219592c0e0ec3bd4200b0c406 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/chMap.m @@ -0,0 +1,41 @@ +function cmap = chMap(M) +%CHMAP Create a monochrome-compatible colour map +% +% CMAP = IOSR.FIGURES.CHMAP returns a colour map CMAP (varying black - +% blue - green - yellow - white) that is monochrome-compatible, i.e. it +% produces a linear greyscale colour map. CMAP is size Mx3, where M is +% the length of the current figure's colormap. If no figure exists, +% MATLAB creates one. +% +% CMAP = IOSR.FIGURES.CHMAP(M) returns a colormap of length M. +% +% EXAMPLE +% +% figure; +% imagesc(sin(linspace(0,2*pi,1000))'*... +% sin(linspace(0,2*pi,1000))); +% colormap(iosr.figures.chMap(256)); +% axis image; +% colorbar +% +% See also IOSR.FIGURES.CMRMAP, GRAY. + +% Copyright 2016 University of Surrey. + + % default colormap size + if nargin < 1, M = size(get(gcf,'colormap'),1); end + + N = linspace(0,1,M)'; + + % Define red and blue components + R = (sin(((2.*N.^1.5)-1).*(pi/2))+1)./2; + B = ((N.^1.25)+((sin((N.^1.0).*(2*pi)))./1.75)); + % Calculate green to ensure monotonic luminance + G = (N - 0.2989.*R - 0.1140.*B)./0.5870; + + % Ensure map is in range [0,1] + cmap = [R G B]; + cmap = cmap-min(cmap(:)); + cmap = cmap./max(cmap(:)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/cmrMap.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/cmrMap.m new file mode 100644 index 0000000000000000000000000000000000000000..ba3f7faec7c049ef7525257b4f8466f85f466e0b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/cmrMap.m @@ -0,0 +1,60 @@ +function cmap = cmrMap(M) +%CMRMAP Create a monochrome-compatible colour map +% +% CMAP = IOSR.FIGURES.CMRMAP returns a colour map CMAP (varying black - +% purple - red - yellow - white) that is monochrome- compatible, i.e. it +% produces a monotonic greyscale colour map. CMAP is size M-by-3, where M +% is the length of the current figure's colormap. If no figure exists, +% MATLAB creates one. +% +% CMAP = IOSR.FIGURES.CMRMAP(M) returns a colormap of length M. +% +% The map is a slight modification to that suggested in [1]. +% +% EXAMPLE +% +% figure; +% imagesc(peaks(1000)); +% colormap(iosr.figures.cmrMap(256)); +% axis image; +% colorbar +% +% REFERENCE +% +% [1] Rappaport, C. 2002: "A Color Map for Effective Black-and-White +% Rendering of Color Scale Images", IEEE Antenna's and Propagation +% Magazine, Vol.44, No.3, pp.94-96 (June). +% +% See also IOSR.FIGURES.CHMAP, GRAY. + +% Copyright 2016 University of Surrey. + + % default colormap size + if nargin < 1, M = size(get(gcf,'colormap'),1); end + + % reference colour map + % adapted from article to produce more linear luminance + CMRref=... + [0 0 0; + 0.1 0.1 0.35; + 0.3 0.15 0.65; + 0.6 0.2 0.50; + 1 0.25 0.15; + 0.9 0.55 0; + 0.9 0.75 0.1; + 0.9 0.9 0.5; + 1 1 1]; + + % Interpolate colormap to colormap size + cmap = zeros(M,3); + for c = [1,3] + cmap(:,c) = interp1((1:9)',CMRref(:,c),linspace(1,9,M)','spline'); + end + % calculate green to ensure linear luminance + cmap(:,2) = (linspace(0,1,M)' - 0.2989.*cmap(:,1) - 0.1140.*cmap(:,3))./0.5870; + + % Limit to range [0,1] + cmap = cmap-min(cmap(:)); + cmap = cmap./max(cmap(:)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/multiwaveplot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/multiwaveplot.m new file mode 100644 index 0000000000000000000000000000000000000000..5355ad3aa0451133a4785396c849a6749dcaa176 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/multiwaveplot.m @@ -0,0 +1,286 @@ +function varargout = multiwaveplot(varargin) +%MULTIWAVEPLOT Stacked line plots from a matrix or vectors +% +% Multiwaveplot draws a series of stacked lines (one on top of the other) +% contained in the rows of an input 2-D matrix. Each line has a +% designated row on the plot; the first row is plotted at the bottom of +% the plot. +% +% IOSR.FIGURES.MULTIWAVEPLOT(Z) draws a series of lines contained in the +% rows of the matrix Z. +% +% IOSR.FIGURES.MULTIWAVEPLOT(X,Y,Z) plot the lines against the data in X +% and Y, such that X specifies the common x-data, and Y determines the +% vertical position of each row. Hence, length(X)==size(Z,2) and +% length(Y)==size(Z,1). +% +% Z may also be a vector, of the same length as X and Y; the data +% contained in X and Y will be used to construct a matrix for plotting. +% +% IOSR.FIGURES.MULTIWAVEPLOT(...,'parameter','value') allows a number of +% options to be specified. The options are: +% +% ({} indicates the default value) +% +% 'gain' : {1} | scalar +% This parameter scales the height of each line. With gain=1 +% (default), the height of the tallest line will be limited so as not +% to encroach on the adjacent line; all other lines are scaled +% accordingly. With gain~=1 the height of each line will +% decrease/increase by a factor gain. +% 'horizonWidth' : {1} | scalar +% The plot can be made to narrower (or wider) at the top, to give the +% impression of a horizon. This may be useful, for example, when y +% data represent time. With horizonWidth=1 (default), the top and +% bottom of the plot have the same width. With horizonWidth<1, the +% plot is narrower at the top by a factor of horizonWidth. With +% horizonWidth>1, the plot is narrower at the bottom by a factor of +% 1/horizonWidth. Specifying horizonWidth>1 will cause the x-axis to +% be moved to the top of the plot. +% 'horizonOffset' : {0} | scalar +% This parameter specifies the vanishing point of the horizon. With +% horizonOffset=0 (default), the vanishing point is in the centre. +% With horizonOffset=-1, the vanishing point is on the left of the +% plot. With horizonOffset=1, the vanishing point is on the right of +% the plot. Intermediate values specify intermediate vanishing +% points. +% 'mode' : {'plot'} | 'fill' +% This parameter plots the data with the specified mode. The default +% mode depends on gain: for gain<=1, mode defaults to 'plot' and +% plots lines for each row of Z. For gain>1, mode defaults to 'fill' +% and instead plots white patch objects for each row of Z, covering +% the area under each line, such that lines with a lower row index +% mask those with a higher row index. +% 'reverseY' : {false} | true +% Determine the order in which data are plotted vertically. With +% reverseY=false (default), the first row is plotted at the bottom of +% the plot. With reverseY=true, the first row is plotted at the top +% of the plot and the axis direction is reversed, but the horizon +% effect is unchanged. In both cases, lower rows are plotted in front +% of higher rows. +% +% H = IOSR.FIGURES.MULTIWAVEPLOT(...) returns a vector of handles to +% patch (for mode = 'fill') or lineseries (for mode = 'plot') graphics +% objects, one handle per line. +% +% See also FILL, PATCH, PLOT, IMAGESC. + +% Copyright 2016 University of Surrey. + + %% Derive inputs + + firstPar = find(cellfun(@(x) ~isnumeric(x),varargin),1,'first'); + if isempty(firstPar) + firstPar = nargin+1; + end + overrides = {}; + + % get inputs + switch firstPar-1 + case 1 + Z = varargin{1}; + X = []; + Y = []; + case 2 + error('iosr:multiwaveplot:nargin','Wrong number of input arguments.') + otherwise + X = varargin{1}; + X = reshape(X,1,length(X)); + Y = varargin{2}; + Y = reshape(Y,1,length(Y)); + Z = varargin{3}; + end + + if firstPar < nargin + overrides = varargin(firstPar:end); + end + + % derive data + if isvector(Z) + assert(~isempty(X), 'iosr:multiwaveplot:invalidX', 'If Z is a vector, you must specify X and Y.') + assert(~isempty(Y), 'iosr:multiwaveplot:invalidY', 'If Z is a vector, you must specify X and Y.') + % if vector, make matrix + assert(length(X)==length(Z) && length(Y)==length(Z), 'iosr:multiwaveplot:invalidInputs', 'If Z is a vector, X and Y must be vectors of the same length.') + x = unique(X)'; + y = unique(Y)'; + wave = NaN(length(y),length(x)); + for n = 1:length(x) + for m = 1:length(y) + IX = X==x(n) & Y==y(m); + wave(m,n) = mean(Z(IX)); + end + end + [r,~] = size(wave); + else + % if matrix + if isempty(X) + X = 1:size(Z,2); + end + if isempty(Y) + Y = 1:size(Z,1); + end + assert(ismatrix(Z), 'iosr:multiwaveplot:invalidZ', 'Z must be a 2-D matrix') + wave = Z; + [r,c] = size(wave); + assert(c==length(X), 'iosr:multiwaveplot:invalidX', 'X must be the same length as Z has columns.') + assert(r==length(Y), 'iosr:multiwaveplot:invalidY', 'Y must be the same length as Z has rows.') + if isempty(X) + x = 1:r; + else + x = reshape(X,1,length(X)); + end + if isempty(Y) + y = 1:c; + else + y = Y; + end + end + + % get options + + options = struct(... + 'gain',1,... + 'mode',[],... + 'horizonWidth',1,... + 'horizonOffset',0,... + 'reverseY',false); + + % read parameter/value inputs + if ~isempty(overrides) % if parameters are specified + % read the acceptable names + optionNames = fieldnames(options); + % count arguments + nArgs = length(overrides); + if round(nArgs/2)~=nArgs/2 + error('iosr:multiwaveplot:nameValuePair','MULTIWAVEPLOT needs propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(overrides,2,[]) % pair is {propName;propValue} + IX = strcmpi(pair{1},optionNames); % find match parameter names + if any(IX) + % do the overwrite + options.(optionNames{IX}) = pair{2}; + else + error('iosr:multiwaveplot:unknownOption','%s is not a recognized parameter name',pair{1}) + end + end + end + + % set default plot mode + if isempty(options.mode) + if options.gain > 1 + options.mode = 'fill'; + else + options.mode = 'plot'; + end + end + + assert(all(diff(x)>=0), 'iosr:multiwaveplot:invalidX', 'X must be increasing') + assert(all(diff(y)>=0), 'iosr:multiwaveplot:invalidY', 'Y must be increasing') + + %% Plot + + % horizon + assert(isscalar(options.horizonWidth), 'iosr:multiwaveplot:invalidHorizonWidth', '''horizonWidth'' must be a scalar.') + assert(isscalar(options.horizonOffset), 'iosr:multiwaveplot:invalidHorizonOffset', '''horizonOffset'' must be a scalar.') + assert(options.horizonWidth>=0, 'iosr:multiwaveplot:invalidHorizonWidth', '''horizonWidth'' must be greater than or equal to 0.') + assert(options.horizonOffset>=-1 && options.horizonOffset<=1, 'iosr:multiwaveplot:invalidHorizonOffset', '''horizonOffset'' must be in the range [-1,1].') + if options.reverseY % correct horizon when axis reversed + options.horizonWidth = 1/options.horizonWidth; + end + % calculate widths + horizonWidths = linspace(1,options.horizonWidth,length(y)); + horizonWidths = horizonWidths./max(horizonWidths); + horizonX = linspace(-1,1,length(x))-options.horizonOffset; + + % data scaling + if min(wave(:))>=0 + adjust = 1; % for positive data (e.g. correlograms) + if options.reverseY + y0 = y(end); + else + y0 = y(1); + end + else + adjust = 0.5; % for wave data varying on zero + if options.reverseY + y0 = y(end)+((options.gain*adjust)*(y(end)-y(end-1))); + else + y0 = y(1)-((options.gain*adjust)*(y(2)-y(1))); + end + end + + wave_max = max(abs(wave(:))); % scale relative to max of wave + + for n = 1:r + if ~all(wave(n,:)==0) % just in case all values are zero + wave(n,:) = (adjust/wave_max).*wave(n,:); + end + end + + scale = zeros(r,1); % this parameter allows for non-linear y-values, scaling each channel accordingly + h = zeros(r,1); + + % plot + ax = newplot; + hold on; + + % plotting order + if options.reverseY + set(ax,'ydir','reverse') + order = 1:r; + shift = @(z,y) y-z; + else + order = r:-1:1; + shift = @(z,y) z+y; + end + + for n = order + % calculate scaling factor + try + scale(n) = y(n+1)-y(n); + catch + scale(n) = y(n)-y(n-1); + end + wave(n,:) = wave(n,:).*scale(n); + % scale data for horizon effect + xinterp = interp1(horizonX,x,horizonWidths(n).*horizonX); + yscale = reshape(shift(options.gain.*wave(n,:),y(n)),1,size(wave,2)); + % plot + switch options.mode + case 'plot' + h(n) = plot(xinterp,yscale,'k'); + case 'fill' + xhor = [x(1) xinterp(1) xinterp xinterp(end) x(end)]; + yhor = [y(n) y(n) yscale y(n) y(n)]; + xa=[xhor(1) xhor xhor(end) xhor(1)]; + ya=[y0 yhor y0 y0]; + IX = ~(isnan(xa) | isnan(ya)); + h(n) = fill(xa(IX),ya(IX),'w'); + otherwise + error('iosr:multiwaveplot:unknownMode','Unknown MODE specified: must be ''fill'' or ''plot''') + end + end + + % look at every row to search for max, taking y offset into account + if options.reverseY + ymin = [y(1)-((options.gain*adjust)*(y(2)-y(1))) y0]; + else + ymin = [y0 y(end)+((options.gain*adjust)*(y(end)-y(end-1)))]; + end + + % set plot parameters + hold off + axis([min(x) max(x) ymin]); % set axis limits + set(gca,'layer','top') % move axis to top layer + ytick = get(gca,'ytick'); + set(gca,'ytick',ytick(ytick<=max(y))); % remove ticks beyond y limits + box on + if options.horizonWidth>1 + set(gca,'XAxisLocation','top') + end + + % output + varargout(1:nargout) = {h}; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/subfigrid.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/subfigrid.m new file mode 100644 index 0000000000000000000000000000000000000000..5358cd3e6f4b1ce3ffae16c623f6a00b1727c2d6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+figures/subfigrid.m @@ -0,0 +1,150 @@ +function pos = subfigrid(nrows,ncols,offset,scale) +%SUBFIGRID Create axis positions for subfigures +% +% The spacing of axes using the subplot command can be quite large, and +% manipulating axis positions after plotting can be tricky. For +% publication quality graphics, it is better to specify the subplot +% position directly, rather than using subplot indices. For example: +% +% figure +% subplot('position',[0.1 0.1 0.2 0.2]) +% plot(rand(20,1)) +% +% This function creates appropriate position vectors, for use in the +% above scenario, based on the number of subplots required. Optional +% scaling and offset parameters allow the size of each subplot to be +% fine-tuned, and space for axis labels to be allotted. All calculations +% are performed in normalized units. +% +% POS = IOSR.FIGURES.SUBFIGRID(NROWS,NCOLS) creates an array of positions +% for positioning axes as subfigures. The array has dimensions [M,P,N]: M +% is the subplot row, N is the subplot column, and P is the position +% vector. By default, each axis will be scaled such that [width height] +% will be [1/NCOLS 1/NROWS]. +% +% POS = IOSR.FIGURES.SUBFIGRID(NROWS,NCOLS,OFFSET) allows a margin OFFSET +% to be specified. This should be a four-element vector specifying the +% margins thus: [left right top bottom]. By default offset=[0 0 0 0]. +% Axes will be scaled to fill the remaining space. +% +% POS = IOSR.FIGURES.SUBFIGRID(NROWS,NCOLS,OFFSET,SCALE) allows the axes +% to be scaled. This should be a two-element vector specifying a scale +% factor that will be applied to each axis; SCALE(1) scales the width, +% SCALE(2) scales the height. The axes will be scaled such that the +% offset margin will be retained. By default SCALE=[1 1]. +% +% If scaling is required, but an offset is not, OFFSET may be set to the +% empty matrix []. +% +% Examples +% +% Example 1 +% +% % Normal use of subfigrid +% scrsz = get(0,'ScreenSize'); +% nrows = 2; +% ncols = 3; +% pos = iosr.figures.subfigrid(nrows,ncols,... +% [0.05 0.01 0.01 0.05],[0.85 0.88]); +% +% figure('units','pixels','position',... +% [scrsz(3)/4,scrsz(4)/4,scrsz(3)/2,scrsz(4)/2]) +% for m = 1:nrows +% for n = 1:ncols +% subplot('position',pos(m,:,n)) +% plot(randn(20,1)) +% end +% end +% +% Example 2 +% +% % Use ind2sub when row/col indices are not available +% scrsz = get(0,'ScreenSize'); +% nrows = 2; +% ncols = 3; +% pos = iosr.figures.subfigrid(nrows,ncols,... +% [0.05 0.01 0.01 0.05],[0.85 0.88]); +% +% figure('units','pixels','position',... +% [scrsz(3)/4,scrsz(4)/4,scrsz(3)/2,scrsz(4)/2]) +% for p = 1:nrows*ncols +% [m,n] = ind2sub([nrows ncols],p); +% subplot('position',pos(m,:,n)) +% plot(randn(20,1)) +% end +% +% See also SUBPLOT. + +% Copyright 2016 University of Surrey. + + %% parse inputs + + if nargin<3 + offset = []; + end + if nargin<4 + scale = []; + end + + assert(isscalar(nrows) & round(nrows)==nrows, 'iosr:subfigrid:invalidInput', 'nrows must be a whole number scalar') + assert(isscalar(ncols) & round(ncols)==ncols, 'iosr:subfigrid:invalidInput', 'ncols must be a whole number scalar') + assert(nrows>=1 & ncols>=1, 'iosr:subfigrid:invalidInput', 'nrows and ncols must be greater than, or equal to, 1.') + + if isempty(offset) + offset = zeros(1,4); + elseif ~(isnumeric(offset) && numel(offset)==4) + error('iosr:subgigrid:offsetInvalid','offset should be a four-element numeric vector') + elseif any(offset<0) + error('iosr:subgigrid:offsetInvalid','offset should not contain any negative values') + else + offset = offset(:)'; + end + + if isempty(scale) + scale = [1 1]; + elseif ~(isnumeric(scale) && numel(scale)==2) + error('iosr:subgigrid:scaleInvalid','scale should be a two-element numeric vector') + elseif any(scale>1) || any(scale<0) + error('iosr:subgigrid:scaleInvalid','scale values should be in the range [0,1]') + else + scale = scale(:)'; + end + + %% calculate positions + + % ignore scale values for dimensions where there is one unit. + if ncols==1 && scale(1)<1 + scale(1) = 1; + warning('iosr:subgigrid:scaleUse','Since there is only one column, scale(1) has no effect (and is consequently set to 1).') + end + if nrows==1 && scale(2)<1 + scale(2) = 1; + warning('iosr:subgigrid:scaleUse','Since there is only one row, scale(2) has no effect (and is consequently set to 1).') + end + + % calculate array of left positions + sub_pos_l = linspace(offset(1),1-offset(2),ncols+1); + width = min(abs(diff(sub_pos_l)))*scale(1); + sub_pos_l = sub_pos_l(1:end-1); + % shift axes to maintain right margin: + sub_pos_l = sub_pos_l+linspace(0,((1-scale(1))*width),ncols); + + % calculate array of bottom positions + sub_pos_b = linspace(1-offset(3),offset(4),nrows+1); + height = min(abs(diff(sub_pos_b)))*scale(2); + sub_pos_b = sub_pos_b(2:end); + % shift axes to maintain top margin: + sub_pos_b = sub_pos_b+linspace(((1-scale(2))*height),0,nrows); + + % create array of positions + pos = zeros(nrows,4,ncols); + for m = 1:nrows + for n = 1:ncols + pos(m,1,n) = sub_pos_l(n); % left + pos(m,2,n) = sub_pos_b(m); % bottom + end + end + pos(:,3,:) = width; + pos(:,4,:) = height; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/cell2csv.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/cell2csv.m new file mode 100644 index 0000000000000000000000000000000000000000..0463ac4b6f55120da9d624d372c57ba80644a487 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/cell2csv.m @@ -0,0 +1,60 @@ +function cell2csv(C,filename) +%CELL2CSV Output a cell array to a CSV file +% +% IOSR.GENERAL.CELL2CSV(C,FILENAME) writes the cell array C to a CSV file +% specified by filename. + +% Copyright 2016 University of Surrey. + + %% make sure filename has a .csv extension + + [pathstr, name, ext] = fileparts(filename); + if ~strcmp(ext,'.csv') + filename = [pathstr filesep name '.csv']; + end + + %% write data + + [nrows,ncols]= size(C); + + % trap and remove cell arrays of strings + IX = cell2mat(cellfun(@iscell,C,'UniformOutput',false)); + C(IX) = cellfun(@char,C(IX),'UniformOutput',false); + + % create file + fid = fopen(filename, 'w'); + + % create format string + format = cell(1,ncols); + ind = cellfun(@ischar,C(2,:)); + format(ind) = {'%s,'}; + format(~ind) = {'%f,'}; + format = wrap(format); + + if any(cellfun(@ischar,C(1,:))~=cellfun(@ischar,C(2,:))) + % the cell array has a heading line + header = repmat({'%s,'},[1,ncols]); + header = wrap(header); + start = 2; + fprintf(fid, header, C{1,:}); + else + % the cell array does not have a heading line + start = 1; + end + + for row=start:nrows + fprintf(fid, format, C{row,:}); + end + + fclose(fid); + +end + +function y = wrap(x) +%WRAP Concatenate cells and add end EOL + + y = cell2mat(x); + i = strfind(y,','); + y = [y(1:i(end)-1) '\n']; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/checkMexCompiled.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/checkMexCompiled.m new file mode 100644 index 0000000000000000000000000000000000000000..2abf94735652006bcbbdc49383c55f38b877c85c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/checkMexCompiled.m @@ -0,0 +1,65 @@ +function checkMexCompiled(varargin) +%CHECKMEXCOMPILED Check if mex file is compiled for system +% +% IOSR.GENERAL.CHECKMEXCOMPILED(SOURCE_FILE) checks whether a mex source +% file SOURCE_FILE is compiled for the current operating system OR +% whether the source file has been modified since it was compiled. It is +% compiled if it does not pass these tests (to the same directory as the +% source file). SOURCE_FILE must be a string that is the name of a source +% file on the MATLAB search path. +% +% IOSR.GENERAL.CHECKMEXCOMPILED(OPTIONS,...,SOURCE_FILE) passes the +% script switches in OPTIONS to the mex compiler, one argument per +% switch. +% +% Example +% +% % check function compiled, with debugging info, and +% % with large-array-handling API +% iosr.general.checkMexCompiled('-g','-largeArrayDims','myfun.c') +% +% See also MEX. + +% Copyright 2016 University of Surrey. + + source_file = varargin{end}; + + % Check input filename + assert(ischar(source_file), 'iosr:checkMexCompiled:invalidFile', 'source_file must be a string') + + % Check extension is specified + assert(~isempty(strfind(source_file,'.')), 'iosr:checkMexCompiled:invalidFile', 'source_file: no file extension specified') + + % Locate source file + [pathstr,name,ext] = fileparts(which(source_file)); + + filename = [pathstr filesep name ext]; % Create filename + mexfilename = [pathstr filesep name '.' mexext]; % Deduce mex file name based on current platform + + if strcmp(pathstr,'') % source file not found + error('iosr:checkMexCompiled:fileNotFound',[source_file ': not found']) + elseif exist(mexfilename,'file')~=3 || get_mod_date(mexfilename)<get_mod_date(filename) + % if source file does not exist or it was modified after the mex file + disp(['Compiling "' name ext '".']) + d = cd; + cd(pathstr) + % compile, with options if appropriate + if length(varargin)>1 + options = varargin{1:end-1}; + mex(options,source_file) + else + mex(source_file) + end + disp('Done.') + cd(d) + end + +end + +function datenum = get_mod_date(file) +%GET_MOD_DATE get file modified date + + d = dir(file); + datenum = d.datenum; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/getContents.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/getContents.m new file mode 100644 index 0000000000000000000000000000000000000000..33f57d642d1e798e235ff88f07bb5919cd0cab6e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/getContents.m @@ -0,0 +1,183 @@ +function [cont,dirflag] = getContents(directory,varargin) +%GETCONTENTS Get the contents of a specified directory +% +% This function returns the contents of a specified directory. +% +% CONT = IOSR.GENERAL.GETCONTENTS(DIRECTORY) returns the files and +% folders in a directory and returns them to the cell array cont. It +% ignores hidden files and folders (those starting '.'). DIRECTORY must +% be a character array (string). +% +% CONT = IOSR.GENERAL.GETCONTENTS(DIRECTORY,'PARAMETER',VALUE) allows +% search options to be specified. The options include: +% 'rec' {false} | true +% Search recursively within the subfolders of the +% specified directory. +% 'path' {'relative'} | 'full' +% Specifies whether returned paths are full or relative +% to the specified directory. +% 'sort' {false} | true +% Specify whether the output is sorted alphabetically. +% 'filter' {'all'} | 'files' | 'folders' | '*.ext' | str +% This option allows a filter to be specified. 'files' +% returns names of all files in the directory. 'folders' +% returns names of all folders in the directory. '*.ext', +% where 'ext' is a user-specified file extension, returns +% all files with the extension '.ext'. str may be any +% string; only elements that contain str will be returned +% (files or folders). str is case-sensitive. +% +% [CONT,DIRFLAG] = IOSR.GENERAL.GETCONTENTS(...) returns a logical array +% DIRFLAG, the same size as CONT, indicating whether each element is a +% directory. +% +% Examples +% +% Ex. 1 +% +% % Return all m-files in the current directory +% +% cont = iosr.general.getContents(cd,'filter','*.m') +% +% Ex. 2 +% +% % Return all files in the current directory and its +% % sub-directories +% +% cont = iosr.general.getContents(cd,'rec',true) +% +% Ex. 3 +% +% % Return all files in current directory with names +% % containing 'foo' +% +% % may return files and folders: +% [cont,dirflag] = iosr.general.getContents(cd,'filter','foo') +% +% % use dirflag to limit: +% cont = cont(~dirflag); + +% Copyright 2016 University of Surrey. + + % parse input arguments and arrange call(s) to 'main', which + % does the actual searching of directories + + assert(ischar(directory), 'iosr:getContents:invalidDir', 'directory must be a character array') + + % Switch trap parses the varargin inputs + % default values + recflag = false; + pathflag = 'relative'; + sortflag = false; + str = 'all'; + % find values + for i = 1:2:length(varargin) + switch lower(varargin{i}) + case 'path' + pathflag=varargin{i+1}; + case 'rec' + recflag=varargin{i+1}; + case 'sort' + sortflag=varargin{i+1}; + case 'filter' + str=varargin{i+1}; + otherwise + error('iosr:getContents:unknownOption','Unknown option: %s\n',varargin{i}); + end + end + + % check input options + assert(ischar(pathflag), 'iosr:getContents:invalidPath', '''path'' option must be a string') + assert(strcmp(pathflag,'relative') | strcmp(pathflag,'full'),... + 'iosr:getContents:invalidPath', ... + '''path'' option must ''relative'' or ''full''') + assert(islogical(recflag) & numel(recflag)==1, 'iosr:getContents:invalidRec', '''rec'' option must be logical') + assert(islogical(sortflag) & numel(sortflag)==1, 'iosr:getContents:invalidSoftFlag', '''sort'' option must be a logical') + assert(ischar(str), 'iosr:getContents:invalidStr', 'str must be a character array') + + % first pass: contents of top-level folder + [cont,dirflag] = main(directory,str); + + % do the recursive bit, if recursion is requested + if recflag + dirs = main(directory,'folders'); + count = length(dirs); + n = 1; + while n <= count % recursion requested + [cont_temp,dirflag_temp] = main(dirs{n},str); % search them + cont = [cont; cont_temp]; %#ok<AGROW> append search results + dirflag = [dirflag; dirflag_temp]; %#ok<AGROW> append search results + sdirs = main(dirs{n},'folders'); + dirs = [dirs; sdirs]; %#ok<AGROW> + count = length(dirs); + n = n+1; + end + end + + % remove full path + if strcmp(pathflag,'relative') + if ~strcmp(directory(end),filesep) + directory = [directory filesep]; + end + for n = 1:length(cont) + cont{n} = strrep(cont{n}, directory, ''); + end + end + + % sort output (case insensitive) + if sortflag + [~,IX] = sort(lower(cont)); + cont = cont(IX); + dirflag = dirflag(IX); + end + +end + +function [cont,dirflag] = main(directory,str) +%MAIN get the contents + + list = struct2cell(dir(directory)); + dirbool = cell2mat(list(cellfun(@islogical,list(:,1)),:)); % return directory flags + list = list(1,:); % keep only file names + X = ~strncmp(list, '.', 1); % remove hidden files (those starting '.') + list = list(X); + list = list(:); % make column vector + dirbool = dirbool(X); + dirbool = dirbool(:); % make column vector + + for n = 1:length(list) + list{n} = fullfile(directory,list{n}); + end + + if nargin > 1 + % find filename extensions + exts = cell(size(list)); + for n = 1:length(list) + [~,~,exts{n}] = fileparts(list{n}); + end + % filter + if strncmp(str,'*.',2) % if extensions are requested + ext = str(2:end); + str = 'ext'; + end + switch lower(str) + case 'files' + Y = ~dirbool; + case 'folders' + Y = dirbool; + case 'ext' + Y = strcmp(exts,ext); + case 'all' + Y = true(size(dirbool)); + otherwise % use literal search string + Y = ~cellfun(@isempty,strfind(list,str)); + end + else + Y = true(size(list)); + end + + % return search results + cont = list(Y); + dirflag = dirbool(Y); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/updateContents.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/updateContents.m new file mode 100644 index 0000000000000000000000000000000000000000..af61ac820958235893ccbd500230529b46b237f7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/updateContents.m @@ -0,0 +1,154 @@ +function updateContents(folder) +%UPDATECONTENTS Create a Contents.m file including subdirectories +% +% IOSR.GENERAL.UPDATECONTENTS scans through the current directory, and +% its subdirectories, and builds a Contents file similar to Matlab's +% report-generated Contents.m files. Any existing Contents.m file will be +% overwritten. +% +% IOSR.GENERAL.UPDATECONTENTS(FOLDER) scans through the directory FOLDER. +% +% Typing +% +% help(FOLDER) +% +% or +% +% help path/to/folder +% +% will display Contents.m in the Command Window, and display links to the +% help for any functions that are in Matlab's search path. +% +% NB: Do not use Matlab's Contents Report generator to edit the +% Contents.m file. Execute this function to update it. + +% Copyright 2016 University of Surrey. + + % apply function in current directory + if nargin<1 + folder = cd; + end + + % check input is valid + assert(ischar(folder), 'iosr:updateContents:invalidPath', '''directory'' should be a charater array (string)') + assert(exist(folder,'dir')==7, 'iosr:updateContents:invalidPath', [folder ' does not exist']) + + % check last character in path is not filesep (e.g. '/') + if strcmp(folder(end),filesep) + folder = folder(1:end-1); + end + fIX = strfind(folder,filesep); fIX = fIX(end); + + % name of file to create + filename = 'Contents.m'; + + % Name of the folder + [~,name] = fileparts(folder); + + % delete if it already exists + if exist([folder filesep filename],'file')==2 + delete([folder filesep filename]) + end + + % get subfolders + dirs = iosr.general.getContents(folder,'filter','folders','rec',true,'path','full','sort',true); + dirs = [{folder}; dirs]; + + % get files + files = cell(0,1); + H1_lines = cell(0,1); + for d = 1:length(dirs) + temp = iosr.general.getContents(dirs{d},'filter','files','sort',true); + if ~isempty(temp) + temp = temp(cellfun(@(x) isempty(strfind(x,'~')),temp)); % remove temporary files + temp = temp(cellfun(@(x) isempty(strfind(x,'.mex')),temp)); % remove compiled mex files + temp = temp(cellfun(@(x) ~strcmp(x,filename),temp)); % remove Contents.m + H1_lines = [H1_lines; {''}; {''}]; %#ok<AGROW> % insert blank lines where no functions will be + % determine package prefix + pkgprefix = strrep(dirs{d},[filesep '+'],'.'); + pkgprefix = strrep(pkgprefix,[filesep '@'],'.'); + dots = strfind(pkgprefix,'.'); + if ~isempty(dots) + pkgprefix = [pkgprefix(dots(1)+1:end) '.']; + else + pkgprefix = ''; + end + for f = 1:length(temp) % read H1 lines + H1_lines = [H1_lines; {get_H1_line([dirs{d} filesep temp{f}])}]; %#ok<AGROW> % add H1 lines + % remove extension from and add package prefix to m-files + [~,fname,ext] = fileparts(temp{f}); + if strcmpi(ext,'.m') + temp{f} = [pkgprefix fname]; + end + end + files = [files; {''}; {upper(dirs{d}(fIX+1:end))}; temp;]; %#ok<AGROW> % add filenames + end + end + + % longest file name (so appropriate space can be added between files and H1 lines + longest_word = max(cellfun(@length,files(cellfun(@(x) ~isempty(x),H1_lines)))); + + % write to output + nrows = length(files); + fid = fopen(filename, 'w'); % open file for writing + fprintf(fid, '%s\n%% \n', ['% ' upper(name)]); + fprintf(fid, '%s\n', ['% Contents file for ' upper(folder(fIX+1:end)) ' and its subfolders.']); + for row=1:nrows + if isempty(H1_lines{row}) + fprintf(fid, '%s\n', ['% ' files{row,:}]); + else + rowfilename = files{row,:}; + [~,name,ext] = fileparts(rowfilename); + if strcmpi(ext,'.m') % remove extension from m files + rowfilename = name; + end + fprintf(fid, '%s\n',['% ' rowfilename repmat(' ',1,longest_word-length(rowfilename)) ' - ' H1_lines{row,:}]); + end + end + fprintf(fid, '%% \n%% %s on %s at %s.\n', 'This file was generated by updateContents.m',datestr(datetime('now'),'dd mmm yyyy'),datestr(datetime('now'),'HH:MM:SS')); + fclose(fid); + +end + +function H1_line = get_H1_line(filename) +%GET_H1_LINE get the H1 line for a file + + [~,name,ext] = fileparts(filename); + H1_line = ''; % default output + if strcmp(ext,'.m') + fid = fopen(filename); % open file + tline = fgetl(fid); % read first line + while ischar(tline) + k = strfind(tline,'%'); % find comment + if ~isempty(k) % if it is found + k = k(1); + ispercents = false(size(tline(k:end))); + ispercents(strfind(tline(k:end),'%'))=true; + start = k+find(~(isspace(tline(k:end)) | ispercents),1,'first')-1; + if ~isempty(start) + tline = tline(start:end); % remove leading space/percent + IX = strfind(lower(tline),lower(name)); + if ~isempty(IX) + if IX(1)==1 + tline = tline(length(name)+1:end); % remove function name + end + tline = strtrim(tline); % remove any leading/trailing space + end + H1_line = tline; + H1_line = strtrim(H1_line); + if ~isempty(H1_line) + if strcmp(H1_line(end),'.') % remove trailing period + H1_line = H1_line(1:end-1); + end + H1_line(1) = upper(H1_line(1)); % capitalize first letter + end + end + tline = -1; % set tline to numeric + else + tline = fgetl(fid); % read next line + end + end + fclose(fid); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/urn.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/urn.m new file mode 100644 index 0000000000000000000000000000000000000000..3feb65a0685938773064af08c1fcd5fc26122e1b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+general/urn.m @@ -0,0 +1,66 @@ +function r = urn(varargin) +%URN Generate random number sequence without duplicates +% +% IOSR.GENERAL.URN(N) returns an N-by-N matrix containing a random +% sequence of integers in the interval 1:N without duplicates. The +% integers are unique down each column. +% +% IOSR.GENERAL.URN(M,N) and IOSR.GENERAL.URN([M,N]) return an M-by-N +% matrix. +% +% IOSR.GENERAL.URN(M,N,P,...) and IOSR.GENERAL.URN([M,N,P,...]) return an +% M-by-N-by-P-by-... array. The integers are unique along the first +% non-singleton dimension. +% +% IOSR.GENERAL.URN(...,[],DIM) creates the random sequence along the +% dimension dim. +% +% This function uses a simple algorithm whereby a series or +% uniformly-distributed random numbers are generated and sorted. The +% returned array r is simply the array of indices specifying the sort +% order. +% +% The function was inspired by an object of the same name in Cycling 74's +% Max/MSP. + +% Copyright 2016 University of Surrey. + + % determines whether dimension specified + dimcheck = false; + + % find an empty matrix in input + empties = find(cellfun(@isempty,varargin)); + if ~isempty(empties) + % if there is an empty matrix (dim specified) + range = 1:empties-1; % input array-size-data range + if length(varargin)>empties % check extra dim input specified + dimcheck = true; % dim has been specified + dim = varargin{empties+1}; % get dim + else + warning('iosr:urn:nodim','Empty array but no dim specified. Using default.') + end + else + % input array-size-data range if no dim specified + range = 1:length(varargin); + end + + % input array-size-data at input + n = cell2mat(varargin(range)); + + % random numbers + c = rand(n); + + % If dim unspecified, find first non-singleton dimension + if ~dimcheck + nsdim = find(size(c)>1,1,'first'); + if isempty(nsdim) + dim = 1; + else + dim = nsdim; + end + end + + % sort the sequence, keeping sort indices as random integers + [~,r] = sort(c,dim); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/boxPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/boxPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..2a9de943648ffbebb7fed510aed72cf913640498 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/boxPlot.m @@ -0,0 +1,2410 @@ +classdef (CaseInsensitiveProperties = true) boxPlot < iosr.statistics.statsPlot +%BOXPLOT Draw a box plot +% +% Use this class to draw box plots. The class provides a number of +% options not included in Matlab's boxplot function. +% +% For each box, the central mark is the median, the box extends +% vertically between the 25th and 75th percentiles, the whiskers extend +% to the most extreme data that are not considered outliers, and the +% outliers are plotted individually. +% +% BOXPLOT can draw boxes for data in Y for an arbitrary number of +% dimensions. If Y is an N-by-P-by-G-by-I-by-J... array then G*I*J*... +% boxes are plotted hierarchically for each column P; i.e. J boxes are +% plotted for each index of I, and J*I boxes are plotted for each index +% of G. +% +% IOSR.STATISTICS.BOXPLOT properties: +% Plotting options: +% addPrctiles - Show additional percentiles using markers and +% labels. The property should be a vector of +% percentiles; each percentile will be plotted +% for each box. The property is empty by +% default. +% addPrctilesColor - Specify the marker color for the additional +% percentile markers. The property should be a +% cell array of strings indicating the color +% for each percentile; the colors will be +% repeated for each box. The default is black. +% addPrctilesLabels - Specify labels for the additional +% percentiles. The property should be a cell +% array of strings. By defualt no label +% is shown. +% addPrctilesMarkers - Specify markers for the additional +% percentiles. The property should be a cell +% array of strings indicating the shape of each +% percentile; the markers will be repeated for +% each box. The default is '*'. +% addPrctilesSize - Specify the marker size for the additional +% percentile markers. The property should be a +% numeric vector indicating the size for each +% percentile; the markers will be repeated for +% each box. The default is 6. +% addPrctilesTxtSize - Specify the font size of the additional +% percentile labels. The property should be a +% numeric scalar. The default is 9. +% boxAlpha - The transparency of the boxes (0 is +% transparent, 1 is opaque). The default is 1. +% boxColor - Fill color of the box. The setting can be a +% color specifier (3-element vector or single +% character), 'auto', 'none', or a handle to a +% colormap function (e.g. @gray); 'auto' means +% that Matlab's default colors are used. The +% default is 'none'. +% boxWidth - The width of the box. The setting can be +% 'auto' (meaning that the width is determined +% automatically) or a scalar (specifying the +% width in x-axis units). The default is +% 'auto'. +% groupLabelFontSize - Specify the font size of the group labels +% when the 'style' option is set to +% 'hierarchy'. The default is 9. +% groupLabelHeight - Specify the height of the area reserved for +% group labels when the 'style' option is set +% to 'hierarchy'. The height is determined +% automatically ('auto') or can be specified in +% scale units. The default is 'auto'. +% groupLabels - If the 'style' option is set to 'hierarchy' +% then these labels will be used to label the +% boxes for each x-group. The parameter should +% be specified as a cell vector whereby the Nth +% element contains a vector of length +% SIZE(Y,N+2). By default, the labels are +% empty. +% groupWidth - Specify the proportion of the x-axis interval +% across which each x-group of boxes should be +% spread. The default is 0.75. +% limit - Mode indicating the limits that define +% outliers. When set to '1.5IQR' or '3IQR', the +% min and max values are Q1-Z*IQR and Q3+Z*IQR, +% where Z = 1.5 or 3 respectively. When set to +% 'none', the min and max values are the min +% and max of the data (in this case there will +% be no outliers). The property may also be +% specified as a two-element vector determining +% the limits as percentiles (e.g. [5,95]). The +% default is '1.5IQR'. +% lineColor - Color of the box outline and whiskers. The +% default is 'k'. +% lineStyle - Style of the whisker line. The default is +% '-'. +% lineWidth - Width, in points, of the box outline, whisker +% lines, notch line, violin, and outlier marker +% edges. The default is 1. +% meanColor - Color of the mean marker when showMean=true. +% The default is 'auto' (see boxColor). +% meanMarker - Marker used for the mean when showMean=true. +% The default is '+'. +% meanSize - Size, in point units, of the mean markers +% when showMean=true. The default is 6. +% medianColor - Color of the median line. The default is +% 'auto' (see boxColor). +% method - The method used to calculate the quantiles, +% labelled according to +% http://en.wikipedia.org/wiki/Quantile. The +% default is 'R-8' whereas the default for +% Matlab is 'R-5'. See +% IOSR.STATISTICS.QUANTILE. +% notch - Logical value indicating whether the box +% should have a notch. The notch is centred on +% the median and extends to �1.58*IQR/sqrt(N), +% where N is the sample size (number of non-NaN +% rows in Y). Generally if the notches of two +% boxes do not overlap, this is evidence of a +% statistically significant difference between +% the medians. The default is false. +% notchDepth - Depth of the notch as a proportion of half +% the box width. The default is 0.4. +% notchLine - Logical value specifying whether to draw a +% horizontal line in the box at the extremes of +% the notch. (May be specified indpendently of +% 'notch'.) The default is false. +% notchLineColor - Color of the notch line when notchLine=true. +% The default is 'k'. +% notchLineStyle - Line style of the notch line when +% notchLine=true. The default is ':'. +% outlierSize - Size, in square points, of the outlier +% marker. The default is 36. +% percentile - Percentile limits of the boxes. The default +% is [25,75]. All other statistics, such as +% those that depend on the IQR (e.g. whisker +% extent and notch height), are unaffected by +% this parameter. +% sampleFontSize - Specify the font size of the sample size +% display (if sampleSize=true). The default is +% 9. +% sampleSize - Specify whether to display the sample size in +% the top-right of each box. The default is +% false. +% scaleWidth - Logical value to specify scaling the width of +% each box according to the square root of the +% sample size. The default is false. +% scatterAlpha - Set the transparency of the scatter markers +% (0 is transparent, 1 is opaque) when +% showScatter=true. The default is 1. +% scatterColor - Scatter marker color for scatter plots of +% underlying data (if showScatter=true). The +% default is [.5 .5 .5]. +% scatterLayer - Set the layer of scatter plots with respect +% to the boxes. Can be set to 'top' or +% 'bottom'. The default is 'top'. +% scatterMarker - Marker used for scatter plots of underlying +% data (if showScatter=true). The default is +% 'x'. +% scatterSize - Size, in square points, of the scatter +% markers (if showScatter=true). The default is +% 36. +% showLegend - Display a legend of the data. The labels can +% be set using the 'groupLabels' option. Note +% that the legend uses the box color, median +% line, or violin fill color to distinguish +% legend entries. If these properties do not +% differ between boxes then an error will be +% returned. +% showMean - Logical value determines whether to display +% the mean of the data for each box. The +% default is false. +% showOutliers - Logical value determines whether to display +% outliers. The default is true. +% showScatter - If set to true, a scatter plot of the +% underlying data for each box will be +% overlayed on the plot. The data will have a +% random x-axis offset with respect to the box +% centre. Data that are outliers are not +% included. The default is false. +% showViolin - If true, a 'violin' [1] kernel density +% outline of the data underlying each box will +% be plotted. The outline is calculated using +% the IOSR.STATISTICS.KERNELDENSITY function. +% The default is false. +% style - Determine whether to show additional x-axis +% labels for the data. If set to 'hierarchy', +% additional hierarchical x-axis labels will be +% added for the plot. The labels can be set +% using the 'groupLabels' option. If set to +% 'normal' (default) no additional labels will +% be plotted. +% symbolColor - Outlier marker color. The default is +% 'auto' (see boxColor). +% symbolMarker - Marker used to denote outliers. The default +% is 'o'. +% theme - Specify a display theme to change multiple +% display properties. The options are: +% 'colorall' : colored boxes (with 0.4 +% alpha), lines, and +% scatter markers (median +% line and mean marker are +% black) +% 'colorlines' : clear boxes, black mean +% markers, colored lines +% and scatter markers +% 'colorboxes' : colored boxes, black +% lines and markers, gray +% scatter markers +% 'default' : clear boxes, colored +% median lines and markers, +% gray scatter markers +% Use the 'themeColors' property to specify the +% color(s) that are used. +% themeColors Colors used when creating the theme. The +% default is 'auto' (see boxColor). +% violinBins - If 'showViolin' is true, this specifes the +% bins used to calculate the kernel density. +% See IOSR.STATISTICS.KERNELDENSITY. +% violinBinWidth - If 'showViolin' is true, this specifes the +% bin width used to calculate the kernel +% density. See IOSR.STATISTICS.KERNELDENSITY. +% violinColor - Fill color for the violins. The default is +% 'none' (see boxColor). +% violinKernel - If 'showViolin' is true, this specifes the +% kernel used to calculate the kernel density. +% See IOSR.STATISTICS.KERNELDENSITY. +% xSeparator - Logical value that when true adds a separator +% line between x groups. The default is false. +% xSpacing - Determine the x-axis spacing of boxes. By +% default ('x'), the data in x are used to +% determine the position of boxes on the x-axis +% (when x is numeric). Alternativley, when set +% to 'equal', boxes are equally-spaced, but the +% data in x are used to label the axis; the +% x-axis ticks are at 1:LENGTH(X). +% handles - Structure containing handles to the various +% objects that constitute the plot. The +% fields/handles are: +% 'axes' : the parent axes of +% the box plot +% 'fig' : the parent figure of +% the box plot +% 'addPrctiles' : chart line objects +% for each additional +% percentile marker +% 'addPrctilesTxt' : text objects for each +% additional percentile +% marker +% 'box' : patch objects for +% each box +% 'medianLines' : line objects for each +% median line +% 'means' : chart line objects +% for each mean marker +% 'notchLowerLines' : line objects for each +% lower notch line +% 'notchUpperLines' : line objects for each +% upper notch line +% 'upperWhiskers' : line objects for each +% upper whisker line +% 'lowerWhiskers' : line objects for each +% lower whisker line +% 'upperWhiskerTips': line objects for each +% upper whisker tip +% 'lowerWhiskerTips': line objects for each +% lower whisker line +% 'outliers' : scatter objects for +% each set of outliers +% 'scatters' : scatter objects for +% each scatter overlay +% 'samplesTxt' : text objects for each +% sample size display +% 'groupsTxt' : text objects for each +% group label +% 'xseps' : line objects for each +% x separator +% 'legend' : the legend object +% +% These properties can be referenced using dot notation - e.g. H.BOXCOLOR +% where H is an instance of the BOXPLOT object - or using the SET and GET +% methods - e.g. GET(H,'BOXCOLOR'). Both methods are case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% Read-only properties: +% x - The x data. +% y - The y data. +% weights - Array giving the weights for the data in y. +% The array must be the same size as y. This +% option may be specified in the constructor. +% statistics - Structure containing the statistics used +% for the box plot. With the exception of +% 'outliers', 'outliers_IX', 'addPrctiles', and +% 'percentile' noted below, each field contains +% a 1-by-P-by-G-by-I-by-J... numeric array of +% values (identical to that returned by +% IOSR.STATISTICS.QUANTILE). The fields are: +% 'addPrctiles' : an A-by-P-by-G... array +% containing the +% additional percentile +% values specified by the +% 'addPrctiles' property, +% where A is the number +% of percentiles in the +% property +% 'percentile' : the percentile limits +% specified by the +% 'percentile' property +% 'median' : the median values +% 'N' : the sample size +% 'PL' : the lower percentiles +% specified by the +% 'percentile' property, +% and the lower limit of +% the boxes (default is +% 25th percentile) +% 'PU' : the upper percentiles +% specified by the +% 'percentile' property, +% and the upper limit of +% the boxes (default is +% 75th percentile) +% 'Q1' : the 25th percentiles +% 'Q3' : the 75th percentiles +% 'IQR' : the inter-quartile +% ranges +% 'mean' : the mean values +% 'min' : the minimum values +% (excl. outliers) +% 'max' : the maximum values +% (excl. outliers) +% 'notch_u' : the upper notch values +% 'notch_l' : the lower notch values +% 'outliers' : a 1-by-P-by-G cell +% array of outlier values +% 'outliers_IX' : a logical array, the +% same size as Y, with +% true values indicating +% outliers +% 'std' : the standard deviations +% +% In addition to the above specifications, some options can be specified +% for each group. Parameters should be specified as a cell array of size +% G-by-I-by-J... . These options are: 'boxColor', 'lineColor', +% 'lineStyle', 'meanColor', 'meanMarker, 'medianColor', 'notchLineColor', +% 'notchLineStyle', 'scatterMarker', 'scatterColor', 'symbolColor', +% 'symbolMarker', 'themeColor', and 'violinColor'. +% +% As noted above, colors may be specified as a colormap function handle +% (e.g. @gray for grayscale colors). The function handle can refer to one +% of the built-in colormap functions, or any other function capable of +% generating valid colormaps. If the specified colormap is one of the +% built-in colormaps 'hot' (@hot), 'gray' (@gray), 'bone' (@bone), +% 'copper' (@copper), or 'pink' (@pink), then boxPlot will take steps to +% try to restrict the range of colors. Specifically, for fills (e.g. +% 'boxColor'), the colors will be restricted such that the minimum +% luminance is 0.33 (in order to not mask dark lines). For lines, the +% colors will be restricted such that the maximum luminance is 0.66 (in +% order that lines are not masked by the white background). +% +% IOSR.STATISTICS.BOXPLOT methods: +% boxPlot - Create the box plot. +% +% See also IOSR.STATISTICS.TAB2BOX, IOSR.STATISTICS.QUANTILE, COLORMAP, +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT, +% IOSR.STATISTICS.FUNCTIONALBOXPLOT, IOSR.STATISTICS.KERNELDENSITY. +% +% References +% +% [1] Hintze, Jerry L.; Nelson, Ray D. (1998). "Violin Plots: A Box +% Plot-Density Trace Synergism". The American Statistician. 52 (2): +% 181?4. + +% Copyright 2016 University of Surrey. + + properties (AbortSet) + addPrctiles = [] % Additional percentiles to plot. + addPrctilesColors % Colors for the additional percentile markers. + addPrctilesLabels = {} % Labels for additional percentiles. + addPrctilesMarkers = {} % Markers for additional percentiles. + addPrctilesSize % Size of the additional percentile markers. + addPrctilesTxtSize % Size of the additional percentile labels text. + boxAlpha = 1 % The transparency of the boxes. + boxColor = 'none' % Fill color of the boxes. + boxWidth = 'auto' % The width of the boxes. + groupLabelFontSize = 9 % The font size of the group labels. + groupLabelHeight = 'auto' % The height of the area reserved for group labels. + groupLabels = [] % Labels used to label the boxes for each x-group. + groupWidth = 0.75 % The proportion of the x-axis interval across which each x-group of boxes should be spread. + limit = '1.5IQR' % Mode indicating the limits that define outliers. + lineColor = 'k' % Color of the box outlines and whiskers. + lineStyle = '-' % Style of the whisker lines. + lineWidth = 1 % Width, in points, of the box outline, whisker lines, notch line, and outlier marker edges. + meanColor = 'auto' % Color of the mean marker. + meanMarker = '+' % Marker used for the mean. + meanSize = 6 % Size, in point units, of the mean markers. + medianColor = 'auto' % Color of the median line. + method = 'R-8' % The method used to calculate the quantiles. + notch = false % Whether the box should have a notch. + notchDepth = 0.4 % Depth of the notch as a proportion of half the box width. + notchLineColor = 'k' % Color of the notch line. + notchLineStyle = ':' % Line style of the notch line. + notchLine = false % Whether to draw a horizontal line in the box at the extremes of the notch. + outlierSize = 6^2 % Size, in square points, of the outlier markers. + percentile = [25,75] % Percentile limits of the box. + sampleFontSize = 9 % Specify the font size of the sample size display. + sampleSize = false % Whether to display the sample size in the top-right of each box. + scaleWidth = false % Scale the width of each box according to the square root of the sample size. + scatterAlpha = 1 % The transparency of the scatter markers. + scatterColor = [.5 .5 .5] % Scatter marker color for scatter plots of underlying data. + scatterLayer = 'top' % The layer of scatter plots with respect to the boxes. + scatterMarker = 'x' % Marker used for scatter plots of underlying data. + scatterSize = 6^2 % Size, in square points, of the scatter markers. + showLegend = false % Draw a legend. + showMean = false % Display the mean of the data for each box. + showOutliers = true % Display outliers. + showScatter = false % Display a scatter plot of the underlying data for each box. + showViolin = false % Display a violin (kernel density) plot for the underlying data. + style = 'normal' % Determine whether to show additional x-axis labels for the data. + symbolColor = 'auto' % Outlier marker color. + symbolMarker = 'o' % Marker used to denote outliers. + theme = 'default' % Control a range of display properties. + themeColors = 'auto' % Colors used when creating the theme. + violinBins = 'auto' % The bins used to calculate the violins. + violinBinWidth = 'auto' % The width of the bins used to calculate the violins. + violinAlpha = 1 % Alpha of the violins. + violinColor = 'none' % Color of the violins. + violinWidth = 'auto' % The width of the violins. + violinKernel = 'normal' % The violin kernel used to calculate the kernel density. + xSeparator = false % Add a separator line between x groups. + xSpacing = 'x' % Determine the x-axis spacing of boxes. + end + + properties (Access = private) + diffx % smallest difference of x axis data + groupXticks % x ticks for every box + groupDims % dimensions of data for each x group + groupRange % scale value range of each x group + xlabels % labels for the x axis + xticks % x-axis tick points + end + + properties (SetAccess = private, Dependent, Hidden) + addPrctilesHandle = [] % Chart line objects objects for the additional percentiles markers. + addPrctilesTxtHandle = [] % Text objects for each additional percentile label. + boxHandles = [] % Patch objects for each box. + mLineHandles = [] % Line objects for each median line. + meanHandles = [] % Chart line objects for each mean marker. + notchLowerLineHandles = [] % Line objects for each lower notch line. + notchUpperLineHandles = [] % Line objects for each upper notch line. + upperWhiskerHandles = [] % Line objects for each upper whisker line. + lowerWhiskerHandles = [] % Line objects for each lower whisker line. + upperWhiskerTipHandles = [] % Line objects for each upper whisker tip. + lowerWhiskerTipHandles = [] % Line objects for each lower whisker tip. + outliersHandles = [] % Scatter objects for each set of outliers. + scatterHandles = [] % Scatter objects for each scatter overlay. + sampleTxtHandes = [] % Text objects for each sample size display. + groupTxtHandes = [] % Text objects for each group label. + xsepHandles = [] % Line objects for each x separator. + legendHandle = [] % Legend object. + end + + methods + + function obj = boxPlot(varargin) + % BOXPLOT Draw a box plot. + % + % IOSR.STATISTICS.BOXPLOT(Y) produces a box plot of the data in + % Y. If Y is a vector, there is just one box. If Y is a matrix, + % there is one box per column. If Y is an + % N-by-P-by-G-by-I-by-J... array then G*I*J*... boxes are plotted + % hierarchically for each column P; i.e. J boxes are plotted for + % each index of I, and J*I boxes are plotted for each index of G. + % For each box, the central mark is the median of the + % data/column, the edges of the box are the 25th and 75th + % percentiles, the whiskers extend to the most extreme data + % points not considered outliers, and outliers are plotted + % individually. NaNs are excluded from the data. + % + % Tabular data can be arranged into the appropriate format using + % the IOSR.STATISTICS.TAB2BOX function. + % + % IOSR.STATISTICS.BOXPLOT(X,Y) specifies the x-axis values for + % each box. X should be a vector, with as many elements as Y has + % columns. The default is 1:SIZE(Y,2). + % + % IOSR.STATISTICS.BOXPLOT(...,'PARAMETER',VALUE) allows the + % plotting options to be specified when the plot is constructed. + % + % IOSR.STATISTICS.BOXPLOT(AX,...) creates the box plot in the + % axes specified by AX. + % + % Examples + % + % Example 1: Basic grouped box plot with legend + % + % y = randn(50,3,3); + % x = [1 2 3.5]; + % y(1:25) = NaN; + % + % figure; + % h = iosr.statistics.boxPlot(x,y,... + % 'symbolColor','k',... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor',{[1 0 0]; [0 1 0]; [0 0 1]},... + % 'groupLabels',{'y1','y2','y3'},... + % 'showLegend',true); + % box on + % + % Example 2: Grouped box plot with overlayed data + % + % figure; + % iosr.statistics.boxPlot(x,y,... + % 'symbolColor','k',... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor','auto',... + % 'showScatter',true); + % box on + % + % Example 3: Grouped box plot with displayed sample sizes + % and variable widths + % + % figure; + % iosr.statistics.boxPlot(x,y,... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor','auto',... + % 'sampleSize',true,... + % 'scaleWidth',true); + % box on + % + % Example 4: Grouped notched box plot with x separators and + % hierarchical labels + % + % figure; + % iosr.statistics.boxPlot({'A','B','C'},y,... + % 'notch',true,... + % 'medianColor','k',... + % 'symbolMarker',{'+','o','d'},... + % 'boxcolor','auto',... + % 'style','hierarchy',... + % 'xSeparator',true,... + % 'groupLabels',{{'Group 1','Group 2','Group 3'}}); + % box on + % + % Example 5: Box plot with legend labels from data + % + % % load data + % % (requires Statistics or Machine Learning Toolbox) + % load carbig + % + % % arrange data + % [y,x,g] = iosr.statistics.tab2box(Cylinders,MPG,when); + % + % % sort + % IX = [1 3 2]; % order + % g = g{1}(IX); + % y = y(:,:,IX); + % + % % plot + % figure + % h = iosr.statistics.boxPlot(x,y,... + % 'symbolColor','k','medianColor','k','symbolMarker','+',... + % 'boxcolor',{[1 1 1],[.75 .75 .75],[.5 .5 .5]},... + % 'scalewidth',true,'xseparator',true,... + % 'groupLabels',g,'showLegend',true); + % box on + % title('MPG by number of cylinders and period') + % xlabel('Number of cylinders') + % ylabel('MPG') + % + % Example 6: Box plot calculated from weighted quantiles + % + % % load data + % load carbig + % + % % random weights + % weights = rand(size(MPG)); + % + % % arrange data + % [y,x,g] = iosr.statistics.tab2box(Cylinders,MPG,when); + % weights_boxed = iosr.statistics.tab2box(Cylinders,weights,when); + % + % % plot + % figure + % h = iosr.statistics.boxPlot(x,y,'weights',weights_boxed); + % + % Example 7: Draw a violin plot + % y = randn(50,3,3); + % x = [1 2 3.5]; + % y(1:25) = NaN; + % figure('color','w'); + % h2 = iosr.statistics.boxPlot(x,y, 'showViolin', true, 'boxWidth', 0.025, 'showOutliers', false); + % box on + + if nargin > 0 + + %% check for deprecated properties + + % check for scatter option + scatterIX = strcmpi('scatter',varargin); + if any(scatterIX) + warning('The ''scatter'' property is deprecated. Use ''showScatter'' instead.'); + varargin{scatterIX} = 'showScatter'; + end + + % check for mean option + meanIX = strcmpi('mean',varargin); + if any(meanIX) + warning('The ''mean'' property is deprecated. Use ''showMean'' instead.'); + varargin{meanIX} = 'showMean'; + end + + %% set x, y, and dims + + % check for input data + start = obj.getXY(varargin{:}); + obj.groupDims = obj.ydims(3:end); + + % create initial theme + obj.createTheme(); + + % check weights + obj.checkWeights(); + + % set properties from varargin + obj.setProperties(start,nargin,varargin); + + % remove NaN columns + obj.removeNaN(); + + % set x axis properties and labels + obj.setXprops(); + + %% statistics + + % calculate statistics + obj.calculateStats(); + + %% draw + + % set handles + obj.parseAxesHandle(varargin{:}); + + % draw the box plot + obj.draw('all'); + + % add listener to ylim so that some properties can be redrawn + addlistener(handle(obj.handles.axes),'YLim','PostSet',... + @(hProp,eventData) obj.eventHandler(hProp,eventData)); + + end + + end + + %% dependent handle getters + + % these are all deprecated and the handles moved to the obj.handles struct + + function val = get.addPrctilesHandle(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.addPrctilesHandle'' is deprecated. Use ''obj.handles.addPrctiles'' instead.'); + val = obj.handles.addPrctiles; + end + + function val = get.addPrctilesTxtHandle(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.addPrctilesTxtHandle'' is deprecated. Use ''obj.handles.addPrctilesTxt'' instead.'); + val = obj.handles.addPrctilesTxt; + end + + function val = get.boxHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.boxHandles'' is deprecated. Use ''obj.handles.box'' instead.'); + val = obj.handles.box; + end + + function val = get.mLineHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.mLineHandles'' is deprecated. Use ''obj.handles.medianLines'' instead.'); + val = obj.handles.medianLines; + end + + function val = get.meanHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.meanHandles'' is deprecated. Use ''obj.handles.means'' instead.'); + val = obj.handles.means; + end + + function val = get.notchLowerLineHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.notchLowerLineHandles'' is deprecated. Use ''obj.handles.notchLowerLines'' instead.'); + val = obj.handles.notchLowerLines; + end + + function val = get.notchUpperLineHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.notchUpperLineHandles'' is deprecated. Use ''obj.handles.notchUpperLines'' instead.'); + val = obj.handles.notchUpperLines; + end + + function val = get.upperWhiskerHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.upperWhiskerHandles'' is deprecated. Use ''obj.handles.upperWhiskers'' instead.'); + val = obj.handles.upperWhiskers; + end + + function val = get.lowerWhiskerHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.lowerWhiskerHandles'' is deprecated. Use ''obj.handles.lowerWhiskers'' instead.'); + val = obj.handles.lowerWhiskers; + end + + function val = get.upperWhiskerTipHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.upperWhiskerTipHandles'' is deprecated. Use ''obj.handles.upperWhiskerTips'' instead.'); + val = obj.handles.upperWhiskerTips; + end + + function val = get.lowerWhiskerTipHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.lowerWhiskerTipHandles'' is deprecated. Use ''obj.handles.lowerWhiskerTips'' instead.'); + val = obj.handles.lowerWhiskerTips; + end + + function val = get.outliersHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.outliersHandles'' is deprecated. Use ''obj.handles.outliers'' instead.'); + val = obj.handles.outliers; + end + + function val = get.scatterHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.scatterHandles'' is deprecated. Use ''obj.handles.scatters'' instead.'); + val = obj.handles.scatters; + end + + function val = get.sampleTxtHandes(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.sampleTxtHandes'' is deprecated. Use ''obj.handles.samplesTxt'' instead.'); + val = obj.handles.samplesTxt; + end + + function val = get.groupTxtHandes(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.groupTxtHandes'' is deprecated. Use ''obj.handles.groupsTxt'' instead.'); + val = obj.handles.groupsTxt; + end + + function val = get.xsepHandles(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.xsepHandles'' is deprecated. Use ''obj.handles.xseps'' instead.'); + val = obj.handles.xseps; + end + + function val = get.legendHandle(obj) + warning('iosr:boxPlot:deprecatedProp','''obj.legendHandle'' is deprecated. Use ''obj.handles.legend'' instead.'); + val = obj.handles.legend; + end + + %% accessor functions + + % set/get additional percentiles + + function val = get.addPrctiles(obj) + val = obj.addPrctiles; + end + + function set.addPrctiles(obj,val) + if ~isempty(val) + assert(isvector(val) && isnumeric(val), 'iosr:boxPlot:addPrctilesVector', '''ADDPRCTILES'' should be a numeric vector') + assert(all(val<=100) && all(val>=0), 'iosr:boxPlot:addPrctilesRange', '''ADDPRCTILES'' values should be in the interval [0,100].') + end + obj.addPrctiles = val; + obj.calculateStats(); + obj.draw('addPrctiles'); + end + + % set/get additional percentiles colors + + function val = get.addPrctilesColors(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesColors,{'k'}); + end + + function set.addPrctilesColors(obj,val) + if ~isempty(val) + assert(iscell(val), 'iosr:boxPlot:addPrctilesColors', '''ADDPRCTILESCOLORS'' should be a cell array') + end + obj.addPrctilesColors = val; + obj.draw(); + end + + % set/get additional percentiles labels + + function val = get.addPrctilesLabels(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesLabels,{''}); + end + + function set.addPrctilesLabels(obj,val) + if ~isempty(val) + assert(iscellstr(val), 'iosr:boxPlot:addPrctilesLabels', '''ADDPRCTILESLABELS'' should be a cell array of strings') + end + obj.addPrctilesLabels = val; + obj.draw(); + end + + % set/get additional percentiles markers + + function val = get.addPrctilesMarkers(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesMarkers,{'*'}); + end + + function set.addPrctilesMarkers(obj,val) + if ~isempty(val) + assert(iscellstr(val), 'iosr:boxPlot:addPrctilesMarkers', '''ADDPRCTILESMARKERS'' should be a cell array of strings') + end + obj.addPrctilesMarkers = val; + obj.draw(); + end + + % set/get additional percentiles marker size + + function val = get.addPrctilesSize(obj) + val = obj.checkAddPrctileProp(obj.addPrctilesSize,6); + end + + function set.addPrctilesSize(obj,val) + if ~isempty(val) + assert(isnumeric(val) && isvector(val), 'iosr:boxPlot:addPrctilesSize', '''ADDPRCTILESSIZE'' should be a numeric vector') + end + obj.addPrctilesSize = val; + obj.draw(); + end + + % set additional percentiles label font size + + function set.addPrctilesTxtSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:addPrctilesTxtSize', '''ADDPRCTILESTXTSIZE'' should be a numeric scalar') + obj.addPrctilesTxtSize = val; + obj.draw(); + end + + % set box alpha + + function set.boxAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:boxAlpha', '''BOXALPHA'' must be a numeric scalar') + obj.boxAlpha = val; + obj.draw('legend'); + end + + % set/get box color + + function val = get.boxColor(obj) + val = obj.checkColor(obj.boxColor,'fill'); + val = obj.groupOption(val,'boxColor'); + end + + function set.boxColor(obj,val) + obj.boxColor = val; + obj.draw('legend'); + end + + % set box width + + function set.boxWidth(obj,val) + assert((isnumeric(val) && isscalar(val)) || strcmpi(val,'auto'), 'iosr:boxPlot:boxWidth', '''BOXWIDTH'' must be a numeric scalar or ''auto''.') + obj.boxWidth = val; + obj.draw('all'); + end + + % set/get group labels + + function val = get.groupLabels(obj) + if prod(obj.groupDims)==numel(obj.groupLabels) && numel(obj.groupLabels)>1 + val = {obj.groupLabels}; + else + val = obj.groupLabels; + end + if ~isempty(val) % use input + assert(isvector(val) && iscell(val),... + 'iosr:boxPlot:groupLabelsType', ... + 'The GROUPLABELS option should be a cell vector'); + valSize = cellfun(@length,val); + assert(prod(obj.outDims(3:end))==prod(valSize), ... + 'iosr:boxPlot:groupLabelsSize', ... + ['The GROUPLABELS option should be a cell vector; ' ... + 'the Nth element should contain a vector of length SIZE(Y,N+2)']) + assert(isequal(obj.outDims(3:end),valSize(1:length(obj.outDims)-2)), ... + 'iosr:boxPlot:groupLabelsSize', ... + ['The GROUPLABELS option should be a cell vector; ' ... + 'the Nth element should contain a vector of length SIZE(Y,N+2)']) + else % create placeholder labels + val = cell(1,length(obj.groupDims)); + c = 1; + for m = 1:length(val) + val{m} = cell(1,obj.groupDims(m)); + for n = 1:obj.groupDims(m) + val{m}{n} = sprintf('Data %d',c); + c = c+1; + end + end + end + end + + function set.groupLabels(obj,val) + obj.groupLabels = val; + obj.draw('style','legend'); + end + + % set group label font size + + function set.groupLabelFontSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:groupLabelsFontSize', '''GROUPLABELFONTSIZE'' must be a numeric scalar.') + obj.groupLabelFontSize = val; + obj.draw(); + end + + % set group label height + + function set.groupLabelHeight(obj,val) + assert(strcmp(val,'auto') || (isnumeric(val) && isscalar(val)), 'iosr:boxPlot:groupLabelHeight', '''GROUPLABELHEIGHT'' must be ''auto'' or a numeric scalar.') + obj.groupLabelHeight = val; + obj.draw('style'); + end + + % set group width + + function set.groupWidth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:groupWidth', '''GROUPWIDTH'' must be a numeric scalar') + obj.groupWidth = val; + obj.setXprops(); + obj.draw('all'); + end + + % set stats limit + + function set.limit(obj,val) + if isnumeric(val) + assert(isnumeric(val) && numel(val)==2, 'iosr:boxPlot:limitSize', '''LIMIT'' must be a two-element numeric vector.') + assert(all(val<=100) && all(val>=0), 'iosr:boxPlot:limitRange', '''LIMIT'' values should be in the interval [0,100].') + if all(val<1) + warning('iosr:boxPlot:limitRange','''LIMIT'' values should be in the interval [0,100].') + end + else + assert(ischar(val), 'iosr:boxPlot:limitType', '''LIMIT'' must be a char or numeric array.') + assert(any(strcmpi(val,{'1.5IQR','3IQR','none'})), 'iosr:boxPlot:limitUnknownOption', '''LIMIT'' parameter not recognised.') + end + obj.limit = val; + obj.calculateStats(); + obj.draw('whiskers','outliers','scatter'); + end + + % get/set line colors + + function val = get.lineColor(obj) + val = obj.checkColor(obj.lineColor,'line'); + val = obj.groupOption(val,'lineColor'); + end + + function set.lineColor(obj,val) + obj.lineColor = val; + obj.draw('legend'); + end + + % get/set line style + + function val = get.lineStyle(obj) + val = obj.groupOption(obj.lineStyle,'lineStyle'); + end + + function set.lineStyle(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:lineStyle', '''LINESTYLE'' must be a char array or cell array of strings.') + obj.lineStyle = val; + obj.draw('legend'); + end + + % set line width + + function set.lineWidth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:lineWidth', '''LINEWIDTH'' must be a numeric scalar.') + obj.lineWidth = val; + obj.draw('all'); + end + + % get/set mean color + + function val = get.meanColor(obj) + val = obj.checkColor(obj.meanColor,'line'); + val = obj.groupOption(val,'meanColor'); + end + + function set.meanColor(obj,val) + obj.meanColor = val; + obj.draw(); + end + + % get/set mean marker + + function val = get.meanMarker(obj) + val = obj.groupOption(obj.meanMarker,'meanMarker'); + end + + function set.meanMarker(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:meanMarker', '''MEANMARKER'' must be a char array or cell array of strings.') + obj.meanMarker = val; + obj.draw(); + end + + % set mean size + + function set.meanSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:meanSize', '''MEANSIZE'' must be a numeric scalar.') + obj.meanSize = val; + obj.draw(); + end + + % get/set median color + + function val = get.medianColor(obj) + val = obj.checkColor(obj.medianColor,'line'); + val = obj.groupOption(val,'medianColor'); + end + + function set.medianColor(obj,val) + obj.medianColor = val; + obj.draw('legend'); + end + + % set stats method + + function set.method(obj,val) + assert(ischar(val), 'iosr:boxPlot:method', '''METHOD'' must be a char array.') + obj.method = val; + obj.calculateStats(); + obj.draw('all'); + end + + % set notch + + function set.notch(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:notch', '''NOTCH'' must be logical.') + obj.notch = val; + obj.draw('boxes'); + end + + % set notch depth + + function set.notchDepth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:notchDepth', '''NOTCHDEPTH'' must be a numeric scalar') + obj.notchDepth = val; + obj.draw('boxes'); + end + + % get/set notch line color + + function val = get.notchLineColor(obj) + val = obj.checkColor(obj.notchLineColor,'line'); + val = obj.groupOption(val,'notchLineColor'); + end + + function set.notchLineColor(obj,val) + obj.notchLineColor = val; + obj.draw(); + end + + % get/set notch line style + + function val = get.notchLineStyle(obj) + val = obj.groupOption(obj.notchLineStyle,'notchLineStyle'); + end + + function set.notchLineStyle(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:notchLineStyle', '''NOTCHLINESTYLE'' must be a char array or cell array of strings.') + obj.notchLineStyle = val; + obj.draw(); + end + + % set notch line + + function set.notchLine(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:notchLine', '''NOTCHLINE'' must be logical.') + obj.notchLine = val; + obj.draw('boxes'); + end + + % set outlier size + + function set.outlierSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:outlierSize', '''OUTLIERSIZE'' must be a numeric scalar.') + obj.outlierSize = val; + obj.draw(); + end + + % set percentile + + function set.percentile(obj,val) + assert(isnumeric(val) && numel(val)==2, 'iosr:boxPlot:percentileSize', '''PERCENTILE'' must be a two-element numeric vector.') + assert(all(val<=100) && all(val>=0), 'iosr:boxPlot:percentileRange', '''PERCENTILE'' values should be in the interval [0,100].') + if all(val<1) + warning('iosr:boxPlot:percentileRange', '''PERCENTILE'' values should be in the interval [0,100].') + end + obj.percentile = val; + obj.calculateStats(); + obj.draw('all'); + end + + % set sample font size + + function set.sampleFontSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:sampleFontSize', '''SAMPLEFONTSIZE'' must be a numeric scalar.') + obj.sampleFontSize = val; + obj.draw(); + end + + % set sample size option + + function set.sampleSize(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:sampleSize', '''SAMPLESIZE'' must be logical.') + obj.sampleSize = val; + obj.draw('boxes'); + end + + % set scale width option + + function set.scaleWidth(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:scaleWidth', '''SCALEWIDTH'' must be logical.') + obj.scaleWidth = val; + obj.draw('boxes','scatter','outliers'); + end + + % set legend + + function set.showLegend(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showLegend', '''SHOWLEGEND'' must be logical.') + obj.showLegend = val; + obj.draw('legend'); + end + + % set show mean option + + function set.showMean(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showMean', '''SHOWMEAN'' must be logical.') + obj.showMean = val; + obj.draw('means'); + end + + % set show outliers option + + function set.showOutliers(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showOutliers', '''SHOWOUTLIERS'' must be logical.') + obj.showOutliers = val; + obj.draw('outliers'); + end + + % set show scatter option + + function set.showScatter(obj,val) + assert(islogical(val) && numel(val)==1, 'iosr:boxPlot:showScatter', '''SHOWSCATTER'' must be logical.') + obj.showScatter = val; + obj.draw('scatter'); + end + + % set scatter alpha + + function set.scatterAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:scatterAlpha', '''SCATTERALPHA'' must be a numeric scalar') + obj.scatterAlpha = val; + obj.draw(); + end + + % get/set scatter color + + function val = get.scatterColor(obj) + val = obj.checkColor(obj.scatterColor,'line'); + val = obj.groupOption(val,'scatterColor'); + end + + function set.scatterColor(obj,val) + obj.scatterColor = val; + obj.draw(); + end + + % set scatter layer + + function set.scatterLayer(obj,val) + assert(ischar(val), 'iosr:boxPlot:scatterLayer', '''SCATTERLAYER'' must be a char array.') + obj.scatterLayer = val; + obj.draw(); + end + + % get/set scatter marker + + function val = get.scatterMarker(obj) + val = obj.groupOption(obj.scatterMarker,'scatterMarker'); + end + + function set.scatterMarker(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:scatterMarker', '''SCATTERMARKER'' must be a char array or cell array of strings.') + obj.scatterMarker = val; + obj.draw(); + end + + % set scatter marker size + + function set.scatterSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:scatterSize', '''SCATTERSIZE'' must be a numeric scalar.') + obj.scatterSize = val; + obj.draw(); + end + + % violin + + function set.showViolin(obj,val) + assert(islogical(val) && isscalar(val), 'iosr:boxPlot:showViolin', '''VIOLIN'' must be logical.') + obj.showViolin = val; + obj.draw('violin','whiskers'); + end + + % set style + + function set.style(obj,val) + assert(ischar(val), 'iosr:boxPlot:styleType', '''STYLE'' must be a char array.') + assert(any(strcmpi(val,{'normal','hierarchy'})), 'iosr:boxPlot:styleOption', '''STYLE'' must be either ''normal'' or ''hierarchy''.') + obj.style = val; + obj.draw('style'); + end + + % get/set outlier symbol color + + function val = get.symbolColor(obj) + val = obj.checkColor(obj.symbolColor,'line'); + val = obj.groupOption(val,'symbolColor'); + end + + function set.symbolColor(obj,val) + obj.symbolColor = val; + obj.draw(); + end + + % get/set outlier symbol marker + + function val = get.symbolMarker(obj) + val = obj.groupOption(obj.symbolMarker,'symbolMarker'); + end + + function set.symbolMarker(obj,val) + assert(ischar(val) || iscellstr(val), 'iosr:boxPlot:symbolMarker', '''SYMBOLMARKER'' must be a char array or cell array of strings.') + obj.symbolMarker = val; + obj.draw(); + end + + % set theme + + function set.theme(obj,val) + assert(ischar(val), 'iosr:boxPlot:theme', '''THEME'' must be a char array.') + obj.theme = val; + obj.createTheme(); + obj.draw('legend'); + end + + % theme color + + function val = get.themeColors(obj) + switch lower(obj.theme) + case {'graylines', 'colorlines', 'default'} + val = obj.checkColor(obj.themeColors,'lines'); + case {'grayboxes', 'colorall', 'colorboxes'} + val = obj.checkColor(obj.themeColors,'fill'); + end + val = obj.groupOption(val,'themeColors'); + end + + function set.themeColors(obj,val) + obj.themeColors = val; + obj.createTheme(); + obj.draw('all'); + end + + % set violin props + + function set.violinBins(obj,val) + assert(isnumeric(val) || strcmpi(val,'auto'), 'iosr:boxPlot:violinBins', '''VIOLINBINS'' must be numeric or ''auto''.') + obj.violinBins = val; + obj.draw('violin','whiskers'); + end + + function set.violinBinWidth(obj,val) + assert((isnumeric(val) && isscalar(val)) || strcmpi(val,'auto'), 'iosr:boxPlot:violinBinWidth', '''VIOLINBINWIDTH'' must be a numeric scalar or ''auto''.') + obj.violinBinWidth = val; + obj.draw('violin','whiskers'); + end + + function set.violinKernel(obj,val) + assert(ischar(val), 'iosr:boxPlot:violinKernel', '''VIOLINKERNEL'' must be a string.') + obj.violinKernel = val; + obj.draw('violin','whiskers'); + end + + function set.violinAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:boxPlot:violinAlpha', '''VIOLINALPHA'' must be a numeric scalar') + obj.violinAlpha = val; + obj.draw('legend'); + end + + function val = get.violinColor(obj) + val = obj.checkColor(obj.violinColor,'fill'); + val = obj.groupOption(val,'violinColor'); + end + + function set.violinColor(obj,val) + obj.violinColor = val; + obj.draw('legend'); + end + + function set.violinWidth(obj,val) + assert((isnumeric(val) && isscalar(val)) || strcmpi(val,'auto'), 'iosr:boxPlot:violinWidth', '''VIOLINWIDTH'' must be a numeric scalar or ''auto''.') + obj.violinWidth = val; + obj.draw('violin','whiskers'); + end + + % set x separator option + + function set.xSeparator(obj,val) + assert(islogical(val) && isscalar(val), 'iosr:boxPlot:xSeparator', '''XSEPARATOR'' must be logical.') + obj.xSeparator = val; + obj.draw('xsep'); + end + + % set x spacing option + + function set.xSpacing(obj,val) + assert(any(strcmpi(val,{'x','equal'})), 'iosr:boxPlot:xSpacing', '''XSPACING'' parameter not recognised.') + obj.xSpacing = val; + obj.setXprops(); + obj.draw('all'); + end + + + end + + methods (Access = protected) + + function draw(obj,varargin) + %DRAW main draw function + + if isfield(obj.handles,'axes') + subidx = cell(1,length(obj.outDims)); + hold on; + for n = 1:prod(obj.outDims) + % get indices + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = [{':'} subidx(2:end)]; + gidx = subidx(3:end); + + % determine where to put tick marks for group labels + obj.groupXticks(subidx{:}) = obj.xticks(subidx{2})+obj.getOffset(subidx); + + % plot individual components + if any(strcmpi('violin',varargin)) || any(strcmpi('all',varargin)) + obj.drawViolin(subidx,subidxAll); + end + if any(strcmpi('boxes',varargin)) || any(strcmpi('all',varargin)) + obj.drawBox(subidx,subidxAll); + end + if any(strcmpi('whiskers',varargin)) || any(strcmpi('all',varargin)) + obj.drawWhiskers(subidx); + end + if any(strcmpi('outliers',varargin)) || any(strcmpi('all',varargin)) + obj.drawOutliers(subidx); + end + if any(strcmpi('scatter',varargin)) || any(strcmpi('all',varargin)) + obj.drawScatter(subidx,gidx,subidxAll); + end + if any(strcmpi('means',varargin)) || any(strcmpi('all',varargin)) + obj.drawMean(subidx); + end + if any(strcmpi('addPrctiles',varargin)) || any(strcmpi('all',varargin)) + obj.drawAddPrctiles(subidx); + end + % change graphics options + obj.drawGroupGraphics(subidx,gidx); + end + % style things + if any(strcmpi('xsep',varargin)) || any(strcmpi('all',varargin)) + obj.drawXsepatator(); + end + if any(strcmpi('style',varargin)) || any(strcmpi('all',varargin)) + obj.drawStyle(); + end + if any(strcmpi('legend',varargin)) || any(strcmpi('all',varargin)) + obj.drawLegend(); + end + % change graphics options + obj.drawGlobalGraphics(); + % set layering + if isfield(obj.handles,'scatters') + uistack(obj.handles.scatters(:),obj.scatterLayer); + end + if isfield(obj.handles,'samplesTxt') + uistack(obj.handles.samplesTxt(:),'top'); + end + if isfield(obj.handles,'means') + uistack(obj.handles.means(:),'top'); + end + if isfield(obj.handles,'addPrctiles') + uistack(obj.handles.addPrctiles(:),'top'); + end + if isfield(obj.handles,'addPrctilesTxt') + uistack(obj.handles.addPrctilesTxt(:),'top'); + end + hold off; + end + end + + function drawViolin(obj,subidx,subidxAll) + %DRAWVIOLIN Draw the violin + + try % to delete the handles first + delete(obj.handles.violin(subidx{:})); + catch + end + + if obj.showViolin + + vBinWidth = obj.replaceAuto(... + obj.violinBinWidth, ... + [], ... + 'Unknown ''VIOLINBINWIDTH'' parameter.'); + + vBins = obj.replaceAuto(... + obj.violinBins, ... + [], ... + 'Unknown ''VIOLINBINS'' parameter.'); + + [d, xd] = iosr.statistics.kernelDensity(obj.y(subidxAll{:}), vBins, vBinWidth, obj.violinKernel); + halfviolinwidth = obj.calcHalfViolinWidth(subidx); + d = halfviolinwidth .* (d ./ max(d)); + obj.handles.violin(subidx{:}) = patch(... + [d; -flipud(d)] + obj.xticks(subidx{2}) + obj.getOffset(subidx), ... + [xd; flipud(xd)],'w','Parent',obj.handles.axes); + + end + + end + + function drawBox(obj,subidx,subidxAll) + %DRAWBOX draw boxes + + try % to delete the handles first + delete(obj.handles.box(subidx{:})); + catch + end + try + delete(obj.handles.medianLines(subidx{:})); + catch + end + try + delete(obj.handles.notchUpperLines(subidx{:})); + catch + end + try + delete(obj.handles.notchLowerLines(subidx{:})); + catch + end + try + delete(obj.handles.samplesTxt(subidx{:})); + catch + end + + % determine half box width + [~, halfboxwidth] = obj.calcBoxWidths(subidx); + + % notch depth + notchdepth = obj.notchDepth*halfboxwidth; + + % main nodes + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + q1 = obj.statistics.PL(subidx{:}); + q3 = obj.statistics.PU(subidx{:}); + md = obj.statistics.median(subidx{:}); + nu = obj.statistics.notch_u(subidx{:}); + nl = obj.statistics.notch_l(subidx{:}); + + % set nodes + if obj.notch % if notch requested + Xnodes = [X-halfboxwidth X-halfboxwidth X-halfboxwidth+notchdepth X-halfboxwidth X-halfboxwidth ... + X+halfboxwidth X+halfboxwidth X+halfboxwidth-notchdepth X+halfboxwidth X+halfboxwidth]; + Ynodes = [q1 nl md nu q3 q3 nu md nl q1]; + else % if not + Xnodes = [X-halfboxwidth X-halfboxwidth X+halfboxwidth X+halfboxwidth]; + Ynodes = [q1 q3 q3 q1]; + + end + + % draw box and set props + obj.handles.box(subidx{:}) = patch(Xnodes,Ynodes,'w','Parent',obj.handles.axes); + + if obj.notchLine % if notchLine requested + obj.handles.notchLowerLines(subidx{:}) = line([X-halfboxwidth X+halfboxwidth],[nl nl],... + 'Parent',obj.handles.axes); + obj.handles.notchUpperLines(subidx{:}) = line([X-halfboxwidth X+halfboxwidth],[nu nu],... + 'Parent',obj.handles.axes); + end + + if obj.notch % if notch requested + % median + obj.handles.medianLines(subidx{:}) = line([X-halfboxwidth+notchdepth X+halfboxwidth-notchdepth], [md md]); + else + % median + obj.handles.medianLines(subidx{:}) = line([X-halfboxwidth X+halfboxwidth],[md md]); + end + set(obj.handles.medianLines(subidx{:}),'linestyle','-'); + + if obj.sampleSize % if sample size requested + [~, halfboxwidth] = obj.calcBoxWidths(subidx); + % set x and y offsets + xoffset = 0.15*halfboxwidth; + yoffset = (xoffset./(max(obj.xticks)-min(obj.xticks))).*(max(obj.y(:))-min(obj.y(:))); + gOffset = obj.getOffset(subidx); + % make text + obj.handles.samplesTxt(subidx{:}) = text(obj.xticks(subidx{2})+gOffset+halfboxwidth-xoffset,... + obj.statistics.PU(subidx{:})-yoffset,... + num2str(sum(~isnan(obj.y(subidxAll{:})))),... + 'horizontalalignment','right','verticalalignment','top'); + end + + end + + function drawWhiskers(obj,subidx) + %DRAWWHISKERS draw the whiskers + + try % to delete the handles first + delete(obj.handles.upperWhiskers(subidx{:})); + catch + end + try + delete(obj.handles.lowerWhiskers(subidx{:})); + catch + end + try + delete(obj.handles.upperWhiskerTips(subidx{:})); + catch + end + try + delete(obj.handles.lowerWhiskerTips(subidx{:})); + catch + end + + % vertices + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + [~, halfboxwidth] = calcBoxWidths(obj,subidx); + + % LQ + obj.handles.lowerWhiskers(subidx{:}) = ... + line([X X],[obj.statistics.min(subidx{:}) obj.statistics.PL(subidx{:})],'Parent',obj.handles.axes); + % UQ + obj.handles.upperWhiskers(subidx{:}) = ... + line([X X],[obj.statistics.max(subidx{:}) obj.statistics.PU(subidx{:})],'Parent',obj.handles.axes); + if ~obj.showViolin + % whisker tips + obj.handles.lowerWhiskerTips(subidx{:}) = ... + line([X-0.5*halfboxwidth X+0.5*halfboxwidth],[obj.statistics.min(subidx{:}) obj.statistics.min(subidx{:})],... + 'linestyle','-','Parent',obj.handles.axes); + obj.handles.upperWhiskerTips(subidx{:}) = ... + line([X-0.5*halfboxwidth X+0.5*halfboxwidth],[obj.statistics.max(subidx{:}) obj.statistics.max(subidx{:})],... + 'linestyle','-','Parent',obj.handles.axes); + end + + end + + function drawOutliers(obj,subidx) + %DRAWOUTLIERS draw the outliers + + try % to delete the handles first + delete(obj.handles.outliers(subidx{:})); + catch + end + + if obj.showOutliers + if ~isempty(obj.statistics.outliers{subidx{:}}) % don't bother if no data + % initial plotting vertices + [~, halfboxwidth] = obj.calcBoxWidths(subidx); + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + % add a random x offset based on data distribution + % use full data to calculate offset + subidxAll = subidx; + subidxAll{1} = ':'; + yScatter = obj.y(subidxAll{':'}); + randOffset = obj.xOffset(yScatter); + ix = obj.statistics.outliers_IX(subidxAll{:}); + ix = ix(~isnan(yScatter)); + randOffset = randOffset(ix); + xScatter = X + (0.8.*halfboxwidth.*randOffset); + obj.handles.outliers(subidx{:}) = scatter(xScatter,obj.statistics.outliers{subidx{:}},... + 'Parent',obj.handles.axes); + end + end + + end + + function drawScatter(obj,subidx,gidx,subidxAll) + %DRAWSCATTER draw the scatter overlay + + try % to delete the handles first + delete(obj.handles.scatters(subidx{:})); + catch + end + + if obj.showScatter + + % get non-outliers + IX = ~obj.statistics.outliers_IX(subidxAll{:}); + subidx4 = [{IX} subidx(2:end)]; + + % get data + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + Y = obj.y(subidx4{:}); + + % calculate x offsets + [~,halfboxwidth] = calcBoxWidths(obj,subidx); + if obj.showViolin + halfboxwidth = max(halfboxwidth, obj.calcHalfViolinWidth(subidx)); + end + xScatter = X + (0.8.*halfboxwidth.*obj.xOffset(Y)); + % plot + yScatter = Y(~isnan(Y)); + obj.handles.scatters(subidx{:}) = scatter(xScatter,yScatter,obj.scatterMarker{gidx{:}}); + set(obj.handles.scatters(subidx{:}),'Parent',obj.handles.axes); + end + + end + + function drawMean(obj,subidx) + %DRAWMEAN drawn the means + + try % to delete the handles first + delete(obj.handles.means(subidx{:})); + catch + end + + if obj.showMean + % x position + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + % plot + obj.handles.means(subidx{:}) = plot(X,obj.statistics.mean(subidx{:}),'Parent',obj.handles.axes); + end + + end + + function drawAddPrctiles(obj,subidx) + %DRAWADDPRCTILES draw additional percentiles + + try + delete(obj.handles.addPrctiles(subidx{:})) + catch + end + + if ~isempty(obj.addPrctiles) + subidx2 = subidx; + % x position + X = obj.xticks(subidx{2}) + obj.getOffset(subidx); + % plot + h = zeros(length(obj.addPrctiles),1); + for m = 1:length(obj.addPrctiles) + subidx2{1} = m; + Y = obj.statistics.addPrctiles(subidx2{:}); + h(m) = plot(X,Y); + text(X,Y,obj.addPrctilesLabels{m},... + 'horizontalAlignment','left',... + 'verticalAlignment','bottom') + end + subidxAll = subidx; + subidxAll{1} = ':'; + obj.handles.addPrctiles(subidxAll{:}) = h; + end + + end + + function drawGroupGraphics(obj,subidx,gidx) + %DRAWGROUPGRAPHICS set graphics options for each group + + % violin colors + if obj.showViolin + set(obj.handles.violin(subidx{:}),... + 'FaceColor',obj.violinColor{gidx{:}},... + 'EdgeColor',obj.lineColor{gidx{:}}); + end + + % box colors + set(obj.handles.box(subidx{:}),... + 'FaceColor',obj.boxColor{gidx{:}},... + 'EdgeColor',obj.lineColor{gidx{:}}); + + % notch line + if obj.notchLine + set(obj.handles.notchLowerLines(subidx{:}),... + 'linestyle',obj.notchLineStyle{gidx{:}},'color',obj.notchLineColor{gidx{:}}); + set(obj.handles.notchUpperLines(subidx{:}),... + 'linestyle',obj.notchLineStyle{gidx{:}},'color',obj.notchLineColor{gidx{:}}); + end + + % median line + set(obj.handles.medianLines(subidx{:}),'color',obj.medianColor{gidx{:}}); + + % whiskers + set([obj.handles.lowerWhiskers(subidx{:}) obj.handles.upperWhiskers(subidx{:})],... + 'color',obj.lineColor{gidx{:}}); + set([obj.handles.lowerWhiskers(subidx{:}) obj.handles.upperWhiskers(subidx{:})],... + 'linestyle',obj.lineStyle{gidx{:}}); + if ~obj.showViolin + set([obj.handles.lowerWhiskerTips(subidx{:}) obj.handles.upperWhiskerTips(subidx{:})],... + 'color',obj.lineColor{gidx{:}}); + end + + % outliers + if ~isempty(obj.statistics.outliers{subidx{:}}) && obj.showOutliers % don't bother if no data + set(obj.handles.outliers(subidx{:}),... + 'marker',obj.symbolMarker{gidx{:}},'MarkerEdgeColor',obj.symbolColor{gidx{:}}); + end + + % scatter + if obj.showScatter + set(obj.handles.scatters(subidx{:}),'MarkerEdgeColor',obj.scatterColor{gidx{:}}); + end + + % means + if obj.showMean + set(obj.handles.means(subidx{:}),... + 'color',obj.meanColor{gidx{:}},... + 'marker',obj.meanMarker{gidx{:}}); + end + + % additional percentiles + if ~isempty(obj.addPrctiles) + subidx2 = subidx; + for m = 1:length(obj.addPrctiles) + subidx2{1} = m; + set(obj.handles.addPrctiles(subidx2{:}),... + 'color',obj.addPrctilesColors{m},... + 'marker',obj.addPrctilesMarkers{m}); + end + end + + end + + function drawGlobalGraphics(obj) + %DRAWGLOBALGRAPHICS set global graphics options + + % violin + if obj.showViolin + set(obj.handles.violin, ... + 'LineWidth',obj.lineWidth, ... + 'FaceAlpha',obj.violinAlpha); + end + + % box colors + set(obj.handles.box,... + 'FaceAlpha',obj.boxAlpha,... + 'LineWidth',obj.lineWidth); + + % sample size + if obj.sampleSize + set(obj.handles.samplesTxt,'fontsize',obj.sampleFontSize); + end + + % notch line + if obj.notchLine + set(obj.handles.notchLowerLines,'linewidth',obj.lineWidth); + set(obj.handles.notchUpperLines,'linewidth',obj.lineWidth); + end + + % median line + set(obj.handles.medianLines,'linewidth',obj.lineWidth); + + % whiskers + set([obj.handles.lowerWhiskers obj.handles.upperWhiskers],... + 'linewidth',obj.lineWidth); + if ~obj.showViolin + set([obj.handles.lowerWhiskerTips obj.handles.upperWhiskerTips],... + 'linewidth',obj.lineWidth); + end + + % outliers + if obj.showOutliers && isfield(obj.handles,'outliers') + set(findobj(obj.handles.outliers,'Type','Scatter'),... + 'SizeData',obj.outlierSize); + end + + % scatter + if obj.showScatter && isfield(obj.handles,'scatters') + set(obj.handles.scatters,'SizeData',obj.scatterSize); + if obj.scatterAlpha<1 + try % older versions do not support MarkerEdgeAlpha + set(obj.handles.scatters,'MarkerEdgeAlpha',obj.scatterAlpha); + catch + warning('This version of Matlab does not support scatter marker transparency.') + end + end + end + + % means + if obj.showMean && isfield(obj.handles,'means') + set(obj.handles.means,'markersize',obj.meanSize); + end + + % set group label font size + if isfield(obj.handles,'groupsTxt') + set(obj.handles.groupsTxt,'FontSize',obj.groupLabelFontSize); + end + + % set additional percentile font size + if ~isempty(obj.addPrctiles) && isfield(obj.handles,'addPrctilesTxt') + set(obj.handles.addPrctilesTxt,'FontSize',obj.addPrctilesTxtSize); + end + + end + + function drawXsepatator(obj) + %DRAWXSEPARATOR draw the x separator lines + + try % to delete the handles first + delete(obj.handles.xseps); + catch + end + + if obj.xSeparator + xlines = obj.xticks(1:end-1)+0.5.*diff(obj.xticks); % line positions + obj.handles.xseps = zeros(size(xlines)); % handles + for n = 1:length(xlines) % draw lines + obj.handles.xseps(n) = line([xlines(n) xlines(n)],get(obj.handles.axes,'ylim'),'color',.5+zeros(1,3)); + end + end + end + + function drawStyle(obj) + %DRAWSTYLE draw the style options + + try % to delete the handles first + delete(obj.handles.groupsTxt); + catch + end + + % get outermost box widths (correct xlim for this) + subidxFirst = cell(1,length(obj.outDims)); + [subidxFirst{:}] = ind2sub(obj.outDims, 1); + [~,halfboxwidthFirst] = calcBoxWidths(obj,subidxFirst); + subidxLast = cell(1,length(obj.outDims)); + [subidxLast{:}] = ind2sub(obj.outDims, prod(obj.outDims)); + [~,halfboxwidthLast] = calcBoxWidths(obj,subidxLast); + + % set default x axis + set(obj.handles.axes,'xtick',obj.xticks,... + 'xlim',[min(obj.xticks)-0.5*obj.diffx-halfboxwidthFirst max(obj.xticks)+0.5*obj.diffx+halfboxwidthLast],... + 'xticklabel',obj.xlabels); + + switch lower(obj.style) + case 'normal' + % do nothing + case 'hierarchy' + + % check grouplabels options + if ~isempty(obj.groupLabels) + assert(isvector(obj.groupLabels) && iscell(obj.groupLabels),... + 'iosr:boxPlot:groupLabelsType', ... + 'The GROUPLABELS option should be a cell vector'); + if ~isempty(obj.outDims(3:end)) + assert(isequal(obj.outDims(3:end),cellfun(@length,obj.groupLabels)),... + 'iosr:boxPlot:groupLabelsSize', ... + ['The GROUPLABELS option should be a cell vector; ' ... + 'the Nth element should contain a vector of length SIZE(Y,N+2)']) + else + assert(cellfun(@length,obj.groupLabels)==1,... + 'iosr:boxPlot:groupLabelsSize', ... + 'The GROUPLABELS option should have length 1 if no grouping dimensions are specified.') + end + end + + % number of label rows + labelrows = length(obj.outDims)-1; + + ylim = get(obj.handles.axes,'ylim'); % need y limitis + + if isnumeric(obj.groupLabelHeight) + labelheight = obj.groupLabelHeight; + else + % determine label height + labelheight = obj.calcLabelHeight(); % y range in units calculated based on normalised height + end + + % determine y centre points of labels based on how many labels + % and their height + ymids = ylim(1) - (labelrows:-1:1).*labelheight + 0.5.*labelheight; + + % clear axis tick labels + set(obj.handles.axes,'xticklabels',[]); + + % put labels on plot + totalticks = prod(obj.outDims(2:end)); % total number of ticks across + allticklocs = sort(obj.groupXticks(:)); % their locations + obj.handles.groupsTxt = []; + for c = labelrows:-1:1 % work down hierarchy + Y = ymids(c); % y location + nskip = totalticks/prod(obj.outDims(2:c+1)); % skip through tick locations based on hierarchy + first = 1:nskip:totalticks; % first tick in group + last = nskip:nskip:totalticks; % last tick in group + labellocs = allticklocs(first) + 0.5.*(allticklocs(last)-allticklocs(first)); % centre point for label location + % work through each label location + for n = 1:length(labellocs) + if c==1 % special case: x axis ticks + gLabel = obj.xlabels{n}; + else % every other group + if isempty(obj.groupLabels) % auto increment label + gLabel = num2str(mod(n-1,obj.outDims(c+1))+1); + else % get from input + gLabel = obj.groupLabels{c-1}(mod(n-1,obj.outDims(c+1))+1); % cyclic index into labels + if isnumeric(gLabel) % convert numbers to strings + gLabel = num2str(gLabel); + end + end + end + % place actual label + t = text(labellocs(n),Y,gLabel,'HorizontalAlignment','center','VerticalAlignment','middle'); + % store info about placement + setappdata(t,'rows',labelrows); + setappdata(t,'row',c); + % add to handles + obj.handles.groupsTxt = [obj.handles.groupsTxt t]; + end + + end + otherwise + error('iosr:boxPlot:unknownStyle','Unkown ''style'' option.') + end + + end + + function drawLegend(obj) + %DRAWLEGEND draw the legend + + try % to delete the handles first + delete(obj.handles.legend); + catch + end + + if obj.showLegend + % dimensions of group data + gDims = cellfun(@length,obj.groupLabels); + if isempty(gDims) + gDims = 1; + end + subidx = cell(1,length(gDims)); + % going to change order of handles + orderidx = cell(1,length(gDims)+1); + order = zeros(prod(gDims),1); + % preallocate legend labels + lgndstr = cell(prod(gDims),1); + for n = 1:prod(gDims) + % use linear index to get group data + [subidx{:}] = ind2sub([gDims 1], n); + % order looks at trailing dimensions first + [orderidx{:}] = ind2sub(fliplr([gDims 1]), n); + orderidx = fliplr(orderidx); + order(n) = sub2ind([gDims 1],orderidx{:}); + % create labels + start = true; % create start of string label + for m = length(subidx):-1:1 % work from end through dimensions + str = obj.ensureString(obj.groupLabels{m}(subidx{m})); + if start % initialise label + lgndstr{n} = str; + start = false; + else % prepend string label + lgndstr{n} = [str ', ' lgndstr{n}]; + end + end + end + % choose target for the legend + if ~obj.arrayElementsEqual(obj.boxColor) + legendTarget = obj.handles.box; + target = 'box'; + elseif ~obj.arrayElementsEqual(obj.medianColor) + legendTarget = obj.handles.medianLines; + target = 'medianLines'; + elseif obj.showViolin && ~obj.arrayElementsEqual(obj.violinColor) + legendTarget = obj.handles.violin; + target = 'violin'; + else + error('iosr:boxPlot:legend','The legend uses the box, median line colors, or violins to create legend entries. However, these items appear to be identical, which would make the legend impossible to interpret. Change the ''boxColor'', ''medianColor'', or ''violinColor'' option.'); + end + % create legend in specified order + if ~isempty(legendTarget) + [obj.handles.legend, icons] = legend(legendTarget(1,1,order),lgndstr(order)); + set(obj.handles.legend,'location','best'); + % add alpha to legend entries + PatchInLegend = findobj([obj.handles.legend; icons(:)], 'type', 'patch'); + if ~isempty(PatchInLegend) + switch lower(target) + case 'box' + set(PatchInLegend, 'facealpha', obj.boxAlpha); + case 'violin' + set(PatchInLegend, 'facealpha', obj.violinAlpha); + end + end + end + end + end + + function createTheme(obj) + %CREATETHEME create the color/line theme + + switch lower(obj.theme) % choose scheme + case 'colorall' + boxalpha = 0.4; + boxcolor = obj.themeColors; + linecolor = 'k'; + linestyle = '-'; + meancolor = 'k'; + mediancolor = 'k'; + notchlinecolor = obj.themeColors; + notchlinestyle = ':'; + scattercolor = obj.themeColors; + symbolcolor = obj.themeColors; + case {'colorlines', 'graylines'} + if strcmpi(obj.theme,'graylines') + warning('iosr:boxPlot:graylines', 'The ''graylines'' theme is deprecated. Use the ''colorlines'' theme instead, and specify ''themeColors'' as @gray.') + end + boxalpha = obj.boxAlpha; + boxcolor = 'none'; + linecolor = 'k'; + linestyle = '-'; + meancolor = 'k'; + mediancolor = obj.themeColors; + notchlinecolor = obj.themeColors; + notchlinestyle = ':'; + scattercolor = obj.themeColors; + symbolcolor = obj.themeColors; + case {'colorboxes', 'grayboxes'} + if strcmpi(obj.theme,'grayboxes') + warning('iosr:boxPlot:grayboxes', 'The ''grayboxes'' theme is deprecated. Use the ''colorboxes'' theme instead, and specify ''themeColors'' as @gray.') + end + boxalpha = obj.boxAlpha; + boxcolor = obj.themeColors; + linecolor = 'k'; + linestyle = '-'; + meancolor = 'k'; + mediancolor = 'k'; + notchlinecolor = 'k'; + notchlinestyle = ':'; + scattercolor = [.5 .5 .5]; + symbolcolor = 'k'; + otherwise + if ~strcmpi(obj.theme,'default') + warning(['Unknown theme ''' obj.theme ''' specified. Using default']) + end + boxalpha = 1; + boxcolor = 'none'; + linecolor = 'k'; + linestyle = '-'; + meancolor = obj.themeColors; + mediancolor = obj.themeColors; + notchlinecolor = 'k'; + notchlinestyle = ':'; + scattercolor = [.5 .5 .5]; + symbolcolor = obj.themeColors; + end + % turn off legend while changing parameters + legendState = obj.showLegend; + obj.showLegend = false; + % set parameters + obj.boxAlpha = boxalpha; + obj.boxColor = boxcolor; + obj.medianColor = mediancolor; + obj.lineColor = linecolor; + obj.lineStyle = linestyle; + obj.meanColor = meancolor; + obj.notchLineColor = notchlinecolor; + obj.notchLineStyle = notchlinestyle; + obj.scatterColor = scattercolor; + obj.symbolColor = symbolcolor; + % turn legend back on if it was on + obj.showLegend = legendState; + end + + function calculateStats(obj) + %CALCULATESTATS calculate the statistic for the box plot + + calculateStats@iosr.statistics.statsPlot(obj); + + % calculate stats + obj.statistics.percentile = obj.percentile; % percentile + outsize = size(obj.statistics.median); + obj.statistics.addPrctiles = zeros([length(obj.addPrctiles) outsize(2:end)]); + obj.statistics.PL = zeros(outsize); % lower percentile + obj.statistics.PU = zeros(outsize); % upper percentile + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(obj.outDims) + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = subidx; + subidxAll{1} = ':'; + if ~isempty(obj.addPrctiles) + obj.statistics.addPrctiles(subidxAll{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),obj.addPrctiles(:)./100,[],obj.method,obj.weights(subidxAll{:})); + end + obj.statistics.PL(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),min(obj.percentile)/100,[],obj.method,obj.weights(subidxAll{:})); + obj.statistics.PU(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),max(obj.percentile)/100,[],obj.method,obj.weights(subidxAll{:})); + end + + % check for notches extending beyond box + if (any(obj.statistics.notch_u(:)>obj.statistics.Q3(:)) || any(obj.statistics.notch_l(:)<obj.statistics.Q1(:))) && (obj.notch || obj.notchLine) + warning('Notch extends beyond quartile. Try setting ''notch'' or ''notchLine'' to false') + end + + end + + function setXprops(obj) + %SETXPROPS set x axis properties + + if isnumeric(obj.x) % x is numeric + obj.xlabels = strtrim(cellstr(num2str(obj.x(:)))); + switch lower(obj.xSpacing) % choose spacing + case 'x' + obj.xticks = obj.x; + obj.diffx = min(diff(obj.x)); + if isempty(obj.diffx) + obj.diffx = 1; + end + case 'equal' + obj.xticks = 1:length(obj.x); + obj.diffx = 1; + otherwise + error('iosr:boxPlot:xSpacing','Unknown xSpacing option specified.') + end + else % x is not numeric + obj.xlabels = obj.x; + obj.xticks = 1:length(obj.x); + obj.diffx = 1; + end + obj.groupRange = obj.groupWidth*obj.diffx; + end + + function out = groupOption(obj,option,name) + %GROUPOPTION convert parameter to format for plotting + + gDims = obj.groupDims; + if length(gDims)==1 + gDims = [gDims 1]; + end + + % checks + if ischar(option) + option = cellstr(option); % ensure string is cell array + elseif isnumeric(option) + option = {option}; + end + if isvector(option) + option = option(:); + end + + % pre-allocate output + out = cell(gDims); + + % create output + if length(option)==1 % repeat if only one specified + for n = 1:prod(gDims) + out(n) = option; + end + elseif isequal(gDims,size(option)) % put into cell array + for n = 1:prod(gDims) + assert(ischar(option{n}) || size(option{n},2)==3, 'iosr:boxPlot:groupOptionFormat', ['Option ''' name ''' is not in the correct format.']) + out(n) = option(n); + end + else + error('iosr:boxPlot:groupOptionSize','Option ''%s'' is not the correct size.',name) + end + + end + + function out = checkColor(obj,color,usage) + %checkColor convert 'auto' color option to RGB + + gDims = obj.groupDims; + out = color; % pass input to output + + if ischar(color) + if strcmpi(color,'auto') + color = @lines; + end + end + + if isa(color,'function_handle') + obj.checkColorHandle(color); + out = cell([gDims 1]); + if any(strcmpi(char(color),{'hot','gray','bone','copper','pink'})) + N = 512; + cmapTest = color(N); + YL = 0.2989.*cmapTest(:,1) + 0.5870*cmapTest(:,2) + 0.1140.*cmapTest(:,3); % luminance + switch lower(usage) + case 'fill' + % ensure minimum luminance of 0.33 + firstLumaIX = find(YL>0.33,1,'first'); + if numel(out)<=N + cmap = cmapTest(round(linspace(firstLumaIX,N,numel(out))),:); % sample color map + else + pad = ceil((firstLumaIX/N)*numel(out)); % pad for the black region + cmap = color(numel(out)+pad); % colormap + cmap = cmap(pad+1:end,:); % remove padded region + end + case 'line' + % ensure maximum luminance of 0.66 + lastLumaIX = find(YL<0.66,1,'last'); + if numel(out)<=N + cmap = cmapTest(round(linspace(1,lastLumaIX,numel(out))),:); % sample color map + else + pad = ceil(((N-lastLumaIX)/N)*numel(out)); % pad for the black region + cmap = color(numel(out)+pad); % colormap + cmap = cmap(1:end-pad,:); % remove padded region + end + end + else + cmap = color(numel(out)); % colormap + end + for n = 1:numel(out) + out{n} = cmap(n,:); + end + end + + end + + function [boxwidth, halfboxwidth] = calcBoxWidths(obj,subidx) + %CALCBOXWIDTHS calculate the box width + + % size of boxes + if ischar(obj.boxWidth) + boxwidth = 0.75*(obj.groupRange/prod(obj.groupDims)); + else + boxwidth = obj.boxWidth; + end + + if obj.scaleWidth + % scale box width according to sample size + maxN = max(obj.statistics.N(:)); + halfboxwidth = 0.5 * (sqrt(obj.statistics.N(subidx{:})/maxN)*boxwidth); + else + % normal box width + halfboxwidth = boxwidth/2; + end + + end + + function halfviolinwidth = calcHalfViolinWidth(obj,subidx) + %HALFVIOLINWIDTH calculate the violin width + + % size of boxes + if ischar(obj.violinWidth) + halfviolinwidth = 0.75*(obj.groupRange/prod(obj.groupDims)); + else + halfviolinwidth = obj.violinWidth; + end + + if obj.scaleWidth + % scale box width according to sample size + maxN = max(obj.statistics.N(:)); + halfviolinwidth = 0.5 * (sqrt(obj.statistics.N(subidx{:})/maxN)*halfviolinwidth); + else + halfviolinwidth = halfviolinwidth / 2; + end + + end + + function labelheight = calcLabelHeight(obj) + %CALCLABELHEIGHT calculate the label height for the axes + + ylim = get(obj.handles.axes,'ylim'); + plotheight = get(obj.handles.axes,'position'); % plot position + plotheight = plotheight(4); % plot height in normalised units + plotrange = abs(diff(ylim)); % y range + labelheight = plotheight*plotrange*0.05; % y range in units calculated based on normalised height + + end + + function offset = getOffset(obj,subidx) + %GET_OFFSET calculate offset for hierarchical data + + dims = obj.outDims(3:end); + subidx = subidx(3:end); + if isempty(dims) || prod(dims)==1 + offset = 0; + else + boxspacing = obj.groupRange/prod(obj.groupDims); + offsetn = (0:prod(dims)-1)-((prod(dims)-1)./2); + n = sub2ind([dims(end:-1:1) 1],subidx{end:-1:1}); + offset = offsetn(n).*boxspacing; + end + + end + + function val = checkAddPrctileProp(obj,init,default) + %CHECKADDPRCTILEPROP check and set default values of additional percentile properties + + val = init(:); + currlength = length(val); + if currlength<length(obj.addPrctiles) + val = [val; cell(length(obj.addPrctiles)-currlength,1)]; + for m = currlength+1:length(obj.addPrctiles) + val(m) = default; + end + end + end + + function eventHandler(obj,hProp,eventData) + %EVENTHANDLER handle axes property change events + + propName = hProp.Name; + propValue = eventData.AffectedObject.(propName); + + % update separator lines + if strcmpi(propName,'YLim') + % correct x separator limits + if isfield(obj.handles,'xseps') + ydata = propValue; + if any(isinf(propValue)) + % inf uses actual data to determine limits + ylim = [NaN NaN]; + children = get(obj.handles.axes,'children'); + for n = 1:length(children) + try + d = get(children(n),'YData'); + ylim(1) = min([ylim(1); d]); + ylim(2) = max([ylim(2); d]); + catch + % ignore objects that don't have YData + end + end + % replace occurences of inf + ydata(isinf(propValue)) = ylim(isinf(propValue)); + end + set(obj.handles.xseps,'YData',ydata); + end + % move group labels up or down + if isfield(obj.handles,'groupsTxt') + labelheight = obj.calcLabelHeight(); + for n = 1:length(obj.handles.groupsTxt) + % current position + pos = get(obj.handles.groupsTxt(n),'Position'); + % new position + rows = getappdata(obj.handles.groupsTxt(n),'rows'); + row = getappdata(obj.handles.groupsTxt(n),'row'); + pos(2) = propValue(1) - (rows-row+.5)*labelheight; + % set it + set(obj.handles.groupsTxt(n),'Position',pos); + end + end + end + + end + + end + + methods (Static, Access = private) + + function offset = xOffset(y) + %XOFFSET create an x offset based on data distribution + + y = y(~isnan(y)); + [d, xd] = iosr.statistics.kernelDensity(y); + d = d./max(d); + + try + maxDisplacement = interp1(xd, d, y); + catch + maxDisplacement = zeros(size(y)); + end + randOffset = rand(size(y));%randperm(numel(y))-1; + randOffset = (2*randOffset) - 1; + % randOffset = (2*randOffset./max(randOffset)) - 1; + offset = randOffset(:) .* maxDisplacement; + + end + + function str = ensureString(val) + %ENSURESTRING ensure input value is a string or convert to a string + + if isnumeric(val) + str = num2str(val); + elseif ischar(val) + str = val; + elseif iscellstr(val) + str = char(val); + else + error('iosr:boxPlot:ensureString','Unable to convert data type to string.') + end + + end + + function equal = arrayElementsEqual(v) + %ARRAYELEMENTSEQUAL check if elements in array are the same + + x = v(:); + if iscell(x) && ~iscellstr(x) + x = cell2mat(x); % convert numeric cell arrays to numeric arrays + end + equal = numel(unique(x))==1; + + end + + function checkColorHandle(fHandle) + %CHECKCOLORHANDLE check whether function handle reurns valid color output + + for N = [1 4 8 16] + assert(isequal(size(fHandle(N)),[N 3]), 'iosr:boxPlot:colorFhandle', ['The color function ''' char(fHandle) ''' does not appear to return a color array of the correct size.']) + cOutput = fHandle(N); + assert(all(cOutput(:)>=0) && all(cOutput(:)<=1), 'iosr:boxPlot:colorFhandleRange', ['The color ''' char(fHandle) ''' function does not appear to return RGB values in the interval [0,1].']) + end + end + + function option = replaceAuto(option, default, errorMsg) + %REPLACEAUTO check for and replace auto parameters + if ischar(option) + if strcmpi(option, 'auto') + option = default; + else + error('iosr:boxPlot:invalidOption',errorMsg) + end + end + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalBoxPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalBoxPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..7299dbe783299ff7571ab1c0e19308b777983fb1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalBoxPlot.m @@ -0,0 +1,365 @@ +classdef (CaseInsensitiveProperties = true) functionalBoxPlot < ... + iosr.statistics.functionalPlot +%FUNCTIONALBOXPLOT Draw a functional boxplot +% +% Use this class to plot a functional boxplot [1]. A functional boxplot +% considers each function as a single observation. The order statistics +% are calculated from the band depth (BD) or modified band depth (MBD) of +% each function; the appearance of the functional boxplot is derived +% analogously to the traditional boxplot. The plot shows the median +% function, the 50% central region, and the functional limits +% ([Q1-1.5*IQR, Q3+1.5*IQR], where Q1 and Q3 are the 25th and 75th +% percentiles respectively, and IQR is the interquartile range). Outliers +% (functions exceeding this limit) may also be plotted. +% +% FUNCTIONALBOXPLOT operates on the array Y, which is an N-by-M-by-P +% array, where N functions are stored across the rows of Y, there are M +% X-values, and there are P functional plots. +% +% IOSR.STATISTICS.FUNCTIONALBOXPLOT properties: +% method - Specifies the method used to calculate +% the band depth. +% outlierLineColor - Specifies the color of the outlier lines. +% outlierLineStyle - Specifies the width of the outlier marker +% line. See 'mainLineWidth' for details of +% how to specify widths. The default is 1. +% +% Additional properties are inherited from +% IOSR.STATISTICS.FUNCTIONALPLOT. +% +% These properties can be referenced using dot notation - e.g. H.METHOD +% where H is an instance of the FUNCTIONALBOXPLOT object - or using +% the SET and GET methods - e.g. GET(H,'METHOD'). Both methods are +% case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% Read-only properties: +% x - The x data. +% y - The y data. +% statistics - Structure containing the statistics used +% for the box plot. With the exception of +% 'outliers', each field contains a 1-by-M-by-P +% numeric array of values (identical to that +% returned by IOSR.STATISTICS.QUANTILE). The +% fields are: +% 'inner_l' : the 25th percentile +% 'inner_u' : the 75th percentile +% 'main' : the values of the +% central line +% 'outer_l' : the lower limits +% 'outer_u' : the upper limits +% 'outliers' : a 1-by-P cell array of +% outlier functions +% +% IOSR.STATISTICS.FUNCTIONALBOXPLOT methods: +% FUNCTIONALBOXPLOT - Create the plot. +% +% References +% +% [1] Sun, Y.; Genton, M. G. (2011). "Functional boxplots". Journal of +% Computational and Graphical Statistics. 20: 316?334. +% doi:10.1198/jcgs.2011.09224 +% +% See also IOSR.STATISTICS.BOXPLOT, IOSR.STATISTICS.QUANTILE, +% IOSR.STATISTICS.FUNCTIONALPLOT, IOSR.STATISTICS.FUNCTIONALSPREADPLOT. + +% Adapted from code originally written by: +% - Ying Sun: sunwards@stat.tamu.edu +% - Marc G. Genton: genton@stat.tamu.edu + + properties (AbortSet) + method = 'mbd' % The method used to calculate the quantiles. + outlierLineColor = 'auto' % Color of the outlier lines + outlierLineStyle = '-' % Width of the outlier lines. + end + + properties (Access = private) + depths + end + + methods + + % constructor + function obj = functionalBoxPlot(varargin) + % FUNCTIONALBOXPLOT Draw a functional boxplot. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(Y) produces a functional + % boxplot of the data in Y. Y should be an N-by-M or N-by-M-by-P + % array, where N functions are stored in the rows of Y, there are + % M X-values, and there are P functional plots. The plot shows + % the median function as the main line, the interquartile range + % as the shaded region, lines showing the limits of the data, and + % lines showing any outlier functions. + % + % Tabular data can be arranged into the appropriate format using + % the IOSR.STATISTICS.TAB2BOX function. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(X,Y) specifies the x-axis + % values for the plot. X should be an M-length vector. The + % default is 1:M. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(...,'PARAMETER',VALUE) + % allows the plotting options to be specified when the plot is + % constructed. + % + % IOSR.STATISTICS.FUNCTIONALBOXPLOT(AX,...) creates the plot + % in the axes specified by AX. + % + % Example + % + % % generate random data + % y = cat(3, randn(100,21), 0.25+randn(100,21)); + % x = 0:20; + % + % % Draw a functional box plot for the first function + % figure + % iosr.statistics.functionalBoxPlot(x, y(:,:,1)); + % title('Functional boxplot.') + % axis tight + % box on + + start = obj.getXY(varargin{:}); + + % check input is valid size + assert(ndims(obj.y) <= 3 && ndims(obj.y) >= 2, ... + 'iosr:functionalBoxPlot:invalidY', ... + 'Y must be a two- or three-dimensional array.'); + + % set the properties of the plot + obj.whiskers = true; + obj.setProperties(start,nargin,varargin); + + % remove NaN columns + obj.removeNaN(); + + % calculate the statistics used in the plot + obj.calculateStats(); + + %% draw + + % set handles + obj.parseAxesHandle(varargin{:}); + + % draw the box plot + obj.draw(); + + end + + %% Accessors / Mutators + + function set.method(obj, val) + obj.method = val; + obj.calculateStats(); + obj.draw(); + end + + function val = get.outlierLineColor(obj) + val = obj.parseColor(obj.outlierLineColor); + end + + function val = get.outlierLineStyle(obj) + val = obj.parseProps(obj.outlierLineStyle, false); + end + + end + + methods (Access = protected) + + % calculate the statistics used in the plot + function calculateStats(obj) + + obj.depths = obj.bandDepth(); + nCurves = size(obj.y, 1); + + % Calculate specific stats + outsize = [1 obj.ydims(2:end)]; + outDimsTemp = [1 1 obj.outDims(3:end)]; + obj.statistics.main = zeros(outsize); + obj.statistics.inner_u = zeros(outsize); + obj.statistics.inner_l = zeros(outsize); + obj.statistics.outer_u = zeros(outsize); + obj.statistics.outer_l = zeros(outsize); + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(outDimsTemp) + [subidx{:}] = ind2sub(outDimsTemp, n); + subidx{2} = ':'; + subidxAll = subidx; + subidxAll{1} = ':'; + + data = obj.y(subidxAll{:}); + + % main statistics + [~,index] = sort(obj.depths,'descend'); + m = ceil(nCurves*0.5); + center = data(index(1:m),:); + inf = min(center); + sup = max(center); + dist = 1.5*(sup-inf); + upper = sup+dist; + lower = inf-dist; + + % outliers + outly = sum(or(data'<=lower'*ones(1,nCurves), data'>=upper'*ones(1,nCurves)))'; + outpoint = find(outly); + outliers = data(outpoint,:); + good = data; + good(outpoint,:)=[]; + maxcurve = max(good); + mincurve = min(good); + + % parent class uses these fields for plotting + obj.statistics.inner_u(subidx{:}) = sup; + obj.statistics.inner_l(subidx{:}) = inf; + obj.statistics.outer_u(subidx{:}) = maxcurve; + obj.statistics.outer_l(subidx{:}) = mincurve; + obj.statistics.main(subidx{:}) = data(index(1),:); + obj.statistics.outliers{n} = outliers; + + end + + end + + % Draw the plot + function draw(obj) + + if isfield(obj.handles,'axes') + + axes(obj.handles.axes); + cla; + hold on; + + % parent class does most of the plotting + draw@iosr.statistics.functionalPlot(obj); + + % plot outlier functions + if length(obj.outDims) > 2 + nlines = obj.outDims(3); + else + nlines = 1; + end + if obj.showOutliers + for n = nlines:-1:1 + % draw inner patch + if ~isempty(obj.statistics.outliers{n}) + obj.handles.outliers{n} = line(obj.x, obj.statistics.outliers{n}, ... + 'linestyle', obj.outlierLineStyle{n}, ... + 'linewidth', obj.outlierLineWidth{n}, ... + 'color', obj.outlierLineColor{n} ... + ); + end + end + else + try + delete(obj.handles.outliers) + catch + end + end + + end + + end + + end + + methods (Access = private) + + % calculate band depth + function depth = bandDepth(obj) + + switch lower(obj.method) + case 'bd2' + depth = obj.BD2(); + case 'bd3' + depth = obj.BD3(); + case 'mbd' + depth = obj.MBD(); + otherwise + error('iosr:functionalBoxPlot:unknownMethod',['Unknown mode ''' obj.method '''']) + end + + end + + + function contg = MBD(obj) + % calculates the generalized band depth of a set of data + n = size(obj.y,1); % size of the data matrix + cont = zeros(n,1,obj.outdims(3)); + for p = 1:obj.outdims(3) + for i=1:(n-1) + for j=(i+1):(n) % consider all possible pairs of functions + cont(:,:,p) = cont(:,:,p)+obj.a(obj.y(:,:,p), [i j]); + end + end + end + contg=cont/obj.combinat(n,2); + end + + function contg = BD3(obj) + % calculate the band depth with J=3. + n=size(obj.y,1); + cont=zeros(n,1,obj.outdims(3)); + % Select three observations from the sample in all the possible ways. + for p = 1:obj.outdims(3) + for i=1:(n-2) + for j=(i+1):(n-1) + for k=(j+1):n + cont(:,:,p) = cont(:,:,p)+obj.estaEntre(obj.y(:,:,p), [i j k])'; % In this subfunction we check which observations from the sample is inside the band delimeted by observations i,j and k. + + end + end + end + end + contg=cont/obj.combinat(n,3); + end + + function contg = BD2(obj) + % calculate the band depth of every observation in the matrix + n=size(obj.y,1); + cont=zeros(n, 1, obj.outdims(3)); + for p = 1:obj.outdims(3) + for i=1:((n+2)/3) + for j=(i+1):(n) % choose pairs of indexes in all the possible ways. + cont(:,:,p) = cont(:,:,p)+obj.estaEntre(obj.y(:,:,p), [i j])'; + end + end + end + contg =cont/obj.combinat(n,2); + end + + end + + methods (Static, Access = private) + + function resultado = a(data, v) + n = size(data,1); + p = size(data,2); + Z = data; + inf=(min(Z(v,:)))'; + sup=(max(Z(v,:)))'; + resul=sum((and(Z'<=sup*ones(1,n),Z'>=inf*ones(1,n)))); + % Proportion of coordinates of each observation from the sample + % that is inside the band delimited by pairs v of functions from the sample. + resultado=(resul/p)'; + end + + function resultados = estaEntre(data, v) + [n,p]=size(data); + Z=data; + inf=min(Z(v,:))'; + sup=max(Z(v,:))'; + resultados=sum((and(Z'<=sup*ones(1,n),Z'>=inf*ones(1,n))))==p; + end + + function combinat = combinat(n,p) + if n<p + combinat=0; + else + combinat = nchoosek(n,p); + end + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..3b1a87d83332c7aa1a457844a1c71efd48920afd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalPlot.m @@ -0,0 +1,387 @@ +classdef (Abstract, CaseInsensitiveProperties = true) functionalPlot < ... + iosr.statistics.statsPlot +%FUNCTIONALPLOT Abstract superclass for functional plots +% +% As an abstract class, this class cannot be instantiated. It provides no +% public methods. The class is a super class for: +% - iosr.statistics.functionalBoxPlot +% - iosr.statistics.functionalSpreadPlot +% +% The class does, however, provide various properties to subclasses. +% +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT properties: +% mainLineColor - Specifies the color of the central line. +% See 'addPrctilesLineColor' for details of +% how to specify colors. The default is +% 'auto'. +% mainLineStyle - Specifies the style of the central line. +% The property may be specified as a char +% array (e.g. '-'), or as a length-P cell +% vector of strings (if passing line styles +% for each functional plot). The default is +% '-'. +% mainLineWidth - Specifies the width of the central line. +% The property may be specified as a +% length-P numeric vector, or as a cell +% vector (if passing line styles for each +% functional plot). The default is 1. +% outerLineColor - Specifies the color of the outer lines. +% See 'mainLineStyle' for details of how to +% specify colors. The default is 'auto'. +% outerLineStyle - Specifies the style of the outer lines. +% See 'mainLineStyle' for details of how to +% specify styles. The default is '-'. +% outerLineWidth - Specifies the width of the outer line. +% See 'mainLineWidth' for details of how to +% specify widths. The default is 1. +% outlierLineWidth - Specifies the width of the outlier marker +% line. See 'mainLineWidth' for details of +% how to specify widths. The default is 1. +% showOutliers - Specifies whether to show outliers. The +% property must be a logical value. The +% default is false. +% spreadAlpha - Set the alpha of the shaded region(s). +% The default is 0.5. +% spreadBorderLineColor - Set the color of the shaded regions' +% / region's border. See +% 'addPrctilesLineColor' for details of how +% to specify colors. The default is 'none'. +% spreadBorderLineWidth - Set the width of the shaded regions' +% / region's border. The default is 1. +% spreadColor - Set the color of the shaded region(s). +% See 'addPrctilesLineColor' for details of +% how to specify colors. The default is +% 'auto'. +% whiskers - Specify whether the box is connected to +% the outer line via a whisker. The line is +% drawn with the same style as the outer +% line. The default is false. +% +% These properties can be referenced using dot notation - e.g. H.BOXCOLOR +% where H is an instance of the FUNCTIONALSPREADPLOT object - or using +% the SET and GET methods - e.g. GET(H,'BOXCOLOR'). Both methods are +% case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% See also IOSR.STATISTICS.BOXPLOT, IOSR.STATISTICS.QUANTILE, +% IOSR.STATISTICS.FUNCTIONALBOXPLOT, +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT, IOSR.STATISTICS.STATSPLOT. + + properties (AbortSet) + mainLineColor = 'auto' % The color of the central line. + mainLineStyle = '-' % The style of the central line. + mainLineWidth = 2 % The width of the central line. + outerLineColor = 'auto' % The color of the outer lines. + outerLineStyle = '-' % The style of the outer lines. + outerLineWidth = 0.5 % The width of the outer lines. + outlierLineWidth = 1 % Width of the outlier marker edges. + showOutliers = true % Turn outliers on and off. + spreadAlpha = 0.5 % The alpha of the shaded regions. + spreadColor = 'auto' % The color of the shaded regions. + spreadBorderLineWidth = 1 % The width of the shaded region borders. + spreadBorderLineColor = 'none' % The color of the shaded region borders. + whiskers = false % Specify whether a line connects the box to the outer lines. + end + + methods + + function set.showOutliers(obj, val) + assert(numel(val)==1 && islogical(val), 'iosr:functionalPlot:invalidShowOutliers', ... + '''SHOWOUTLIERS'' must be true or false.') + obj.showOutliers = val; + obj.draw(); + end + + % main lines + + function val = get.mainLineColor(obj) + val = obj.parseColor(obj.mainLineColor); + end + + function set.mainLineColor(obj,val) + obj.mainLineColor = val; + obj.draw(); + end + + function val = get.mainLineStyle(obj) + val = obj.parseProps(obj.mainLineStyle, false); + end + + function set.mainLineStyle(obj,val) + obj.mainLineStyle = val; + obj.draw(); + end + + function val = get.mainLineWidth(obj) + val = obj.parseProps(obj.mainLineWidth, false); + end + + function set.mainLineWidth(obj,val) + obj.mainLineWidth = val; + obj.draw(); + end + + % outer lines + + function val = get.outerLineColor(obj) + val = obj.parseColor(obj.outerLineColor); + end + + function set.outerLineColor(obj,val) + obj.outerLineColor = val; + obj.draw(); + end + + function val = get.outerLineStyle(obj) + val = obj.parseProps(obj.outerLineStyle, false); + end + + function set.outerLineStyle(obj,val) + obj.outerLineStyle = val; + obj.draw(); + end + + function val = get.outerLineWidth(obj) + val = obj.parseProps(obj.outerLineWidth, false); + end + + function set.outerLineWidth(obj,val) + obj.outerLineWidth = val; + obj.draw(); + end + + % outlier settings + + function val = get.outlierLineWidth(obj) + val = obj.parseProps(obj.outlierLineWidth, false); + end + + function set.outlierLineWidth(obj,val) + obj.outlierLineWidth = val; + obj.draw(); + end + + % set spread alpha + + function set.spreadAlpha(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:functionalPlot:invalidSpreadAlpha', ... + '''SPREADALPHA'' must be a numeric scalar') + obj.spreadAlpha = val; + obj.draw(); + end + + % get/set spread line colors + + function val = get.spreadBorderLineColor(obj) + val = obj.parseColor(obj.spreadBorderLineColor); + end + + function set.spreadBorderLineColor(obj,val) + obj.spreadBorderLineColor = val; + obj.draw(); + end + + % set spread border line width + + function set.spreadBorderLineWidth(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:functionalPlot:invalidspreadBorderLineWidth', ... + '''SPREADBORDERLINEWIDTH'' must be a numeric scalar') + obj.spreadBorderLineWidth = val; + obj.draw(); + end + + % set/get spread color + + function val = get.spreadColor(obj) + val = obj.parseColor(obj.spreadColor); + end + + function set.spreadColor(obj,val) + obj.spreadColor = val; + obj.draw(); + end + + % whisker + + function set.whiskers(obj,val) + assert(islogical(val) && isscalar(val), 'iosr:functionalPlot:invalidWhiskers', ... + '''whisker'' must be a scalar and logical'); + obj.whiskers = val; + obj.draw(); + end + + end + + methods (Access = protected) + + % Draw the plot + function draw(obj) + + if isfield(obj.handles,'axes') + + axes(obj.handles.axes); + hold on; + + if length(obj.outDims) > 2 + nlines = obj.outDims(3); + else + nlines = 1; + end + for n = nlines:-1:1 + % draw inner patch + obj.handles.spreads(n) = patch(... + [obj.x obj.x(end:-1:1)], ... + [obj.statistics.inner_u(:,:,n) obj.statistics.inner_l(:,end:-1:1,n)], ... + obj.spreadColor{n} , ... + 'FaceAlpha', obj.spreadAlpha, ... + 'EdgeColor', obj.spreadBorderLineColor{n}, ... + 'LineWidth', obj.spreadBorderLineWidth ... + ); + end + + for n = nlines:-1:1 + + % draw outer limits + obj.handles.outer_u(n) = line(obj.x, obj.statistics.outer_u(:,:,n), ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n} ... + ); + obj.handles.outer_l(n) = line(obj.x, obj.statistics.outer_l(:,:,n), ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n} ... + ); + + % draw centre line + obj.handles.main(n) = line(obj.x, obj.statistics.main(:,:,n), ... + 'linestyle', obj.mainLineStyle{n}, ... + 'linewidth', obj.mainLineWidth{n}, ... + 'color', obj.mainLineColor{n} ... + ); + + end + + % draw whiskers + if obj.whiskers + x_range = max(obj.x) - min(obj.x); + whisker_xlim = [(min(obj.x) + (1/3)*x_range) (max(obj.x) - (1/3)*x_range)]; + if nlines==1 + whisker_x = mean(whisker_xlim); + else + whisker_x = linspace(whisker_xlim(1),whisker_xlim(2),nlines); + end + for n = nlines:-1:1 + % interpolate to find y + [~,x_ix] = min(abs(obj.x-whisker_x(n))); + x_interp_ix = [max(1,x_ix-1) x_ix min(length(obj.x),x_ix+1)]; + x_interp_ix = unique(x_interp_ix); + y_i_l = interp1(obj.x(x_interp_ix), obj.statistics.inner_l(:,x_interp_ix,n), whisker_x(n)); + y_i_u = interp1(obj.x(x_interp_ix), obj.statistics.inner_u(:,x_interp_ix,n), whisker_x(n)); + y_o_l = interp1(obj.x(x_interp_ix), obj.statistics.outer_l(:,x_interp_ix,n), whisker_x(n)); + y_o_u = interp1(obj.x(x_interp_ix), obj.statistics.outer_u(:,x_interp_ix,n), whisker_x(n)); + + % plot + obj.handles.whiskers_l(n) = line([whisker_x(n) whisker_x(n)],[y_i_l y_o_l], ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n}); + obj.handles.whiskers_u(n) = line([whisker_x(n) whisker_x(n)],[y_i_u y_o_u], ... + 'linestyle', obj.outerLineStyle{n}, ... + 'linewidth', obj.outerLineWidth{n}, ... + 'color', obj.outerLineColor{n}); + end + else + try + delete(obj.handles.whiskers_l(n)) + delete(obj.handles.whiskers_u(n)) + catch + end + end + end + + end + + end + + methods (Access = protected) + + % Make properties in to a cell array + function val = parseProps(obj, prop, addP) + + nLines = obj.outDims(3); + if ~addP + nAdd = 1; + else + nAdd = length(obj.addPrctiles); + end + val = cell(nLines, nAdd); + if isnumeric(prop) + cellprop = num2cell(prop); + elseif ischar(prop) + cellprop = cellstr(prop); + else + cellprop = prop; + end + try + for n = 1:nLines + if ~addP + val(n) = cellprop(mod(n-1, numel(cellprop)) + 1); + else + for p = 1:nAdd + ixn = mod(n-1, size(cellprop, 1)) + 1; + ixp = mod(p-1, size(cellprop, 2)) + 1; + val(n,p) = cellprop(ixn, ixp); + end + end + end + catch + keyboard + end + + end + + % Put colors in to a cell array + function val = parseColor(obj, inColor) + + nLines = obj.outDims(3); + val = cell(nLines, 1); + if isnumeric(inColor) + if size(inColor, 2) ~= 3 + error('iosr:functionalPlot:colorInvalid','Color must be an N-by-3 array, where N is any positive integer.') + end + for n = 1:nLines + val(n,:) = {inColor(mod(n, size(inColor, 1)) + 1, :)}; + end + elseif ischar(inColor) + if strcmp(inColor, 'auto') + colors = lines(nLines); + for n = 1:nLines + val(n,:) = {colors(n, :)}; + end + else + colors = cellstr(inColor); + for n = 1:nLines + val(n,:) = colors(mod(n, size(inColor, 1)) + 1); + end + end + elseif isa(inColor,'function_handle') + colors = inColor(nLines); + for n = 1:nLines + val(n,:) = {colors(mod(n, numel(inColor)) + 1)}; + end + elseif iscellstr(inColor) + for n = 1:nLines + val(n,:) = inColor(mod(n, numel(inColor)) + 1); + end + else + error('iosr:functionalPlot:invalidColorFormat','Invalid color format specified.') + end + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalSpreadPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalSpreadPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..1a2f58fc3e8a0f8c884adbfac2761dcc56a0e88c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/functionalSpreadPlot.m @@ -0,0 +1,535 @@ +classdef (CaseInsensitiveProperties = true) functionalSpreadPlot < ... + iosr.statistics.functionalPlot +%FUNCTIONALSPREADPLOT Draw a functional plot showing data spread +% +% Use this class to plot the spread of data against a continuous +% variable. The class calculates point-wise statistics for each set of +% observations on the x-axis. For a plot of spread where each _function_ +% constitutes a single observation, use IOSR.STATISTICS.FUNCTIONALBOXPLOT +% instead. +% +% Measures of spread include parametric and non-parametric confidence +% intervals, interquartile range, standard deviation, or arbitrary +% percentile ranges. The spread is indicated by a shaded region, with a +% central line indicating the primary metric (mean or median). Additional +% percentiles, outliers, and the limits of the data may also be plotted. +% +% FUNCTIONALSPREADPLOT operates on the array Y, which is an N-by-M-by-P +% array, where N observations for each X value are stored in the columns +% of Y, there are M X-values, and there are P functional plots. +% +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT properties: +% addPrctiles - Plot lines for additional percentiles. +% The property should be a vector of +% percentiles; each percentile will be +% plotted for each functional plot. The +% property is empty by default. +% addPrctilesLineColor - Specify the line colors for the +% additional percentile lines. The property +% may be specified using any valid MATLAB +% color specifier. Multiple colors (for +% multiple function plots) may be specified +% by passing colors in a length-P cell +% vector, or by passing a color map +% function handle. The default is 'auto', +% which uses Matlab's 'line' color map. +% addPrctilesLineStyle - Specify the line styles for the +% additional percentile lines. The property +% may be specified as a char array (e.g. +% '-'), or as a P-by-Q cell array of +% strings, where Q is the number of +% additional percentiles. The default is +% '--'. +% addPrctilesLineWidth - Specify the line widths for the +% additional percentile lines. The property +% may be specified as a numeric array (e.g. +% '-'), or as a P-by-Q cell array, where Q +% is the number of additional percentiles. +% The default is 1. +% innerMode - Specify the mode for plotting the inner +% shaded area of the plot. The options are: +% - 'quartile' : the 25th to 75th +% percentile +% (interquartile range) +% - 'std' : the standard deviation +% - 'notch' : the non-parametric +% confidence interval (see +% iosr.statistics.boxPlot) +% - 'ci90' : the 90% confidence +% interval +% - 'ci95' : the 95% confidence +% interval +% - 'ci99' : the 99% confidence +% interval +% The default is 'quartile'. +% limit - Specifies the mode indicating the limits +% that define outliers. See +% iosr.statistics.boxPlot. The default is +% '1.5IQR'. +% mainMode - Specifies the statistic used for the +% central line. The options are 'median' or +% 'mean'. The default is 'median'. +% method - Specifies the method used to calculate +% the quantiles. See +% iosr.statistics.boxPlot. The default is +% 'R-8'. +% outerMode - Specifies what the outer lines plot. The +% options are 'limit' (plots the limits of +% the data as determined by the 'limit' +% option) or 'none'. +% outlierSize - Specifies the size, in square points, of +% the outlier markers. The default is 36. +% outlierEdgeColor - Specifies the color of the outlier marker +% edges. See 'addPrctilesLineColor' for +% details of how to specify colors. The +% default is 'auto'. +% outlierFaceColor - Specifies the color of the outlier marker +% faces. See 'addPrctilesLineColor' for +% details of how to specify colors. The +% default is 'none'. +% outlierMarker - Specifies the markers used for the +% outliers. The property may be specified +% as a char array (e.g. '+'), or as a cell +% array of strings (if passing markers for +% each functional plot). The default is +% '+'. +% +% Additional properties are inherited from +% IOSR.STATISTICS.FUNCTIONALPLOT. +% +% These properties can be referenced using dot notation - e.g. H.LIMIT +% where H is an instance of the FUNCTIONALSPREADPLOT object - or using +% the SET and GET methods - e.g. GET(H,'LIMIT'). Both methods are +% case-insensitive. +% +% Note that some handles will be empty unless the associated option is +% turned on. +% +% Read-only properties: +% x - The x data. +% y - The y data. +% weights - Array giving the weights for the data in y. +% The array must be the same size as y. +% statistics - Structure containing the statistics used +% for the box plot. With the exception of +% 'outliers', 'outliers_IX', 'addPrctiles', and +% 'percentile' noted below, each field contains +% a 1-by-M-by-P numeric array of values +% (identical to that returned by +% IOSR.STATISTICS.QUANTILE). The fields are: +% 'addPrctiles' : an A-by-M-by-P... array +% containing the +% additional percentile +% values specified by the +% 'addPrctiles' property, +% where A is the number +% of percentiles in the +% property +% 'percentile' : the percentile limits +% specified by the +% 'percentile' property +% 'median' : the median values +% 'N' : the sample size +% 'Q1' : the 25th percentiles +% 'Q3' : the 75th percentiles +% 'inner_l' : the inner shaded area's +% lower limit +% 'inner_u' : the inner shaded area's +% upper limit +% 'IQR' : the inter-quartile +% ranges +% 'main' : the values of the +% central line +% 'mean' : the mean values +% 'min' : the minimum values +% (excl. outliers) +% 'max' : the maximum values +% (excl. outliers) +% 'notch_u' : the upper notch values +% 'notch_l' : the lower notch values +% 'outer_l' : the outer line's lower +% limit +% 'outer_u' : the outer line's upper +% limit +% 'outliers' : a 1-by-M-by-P cell +% array of outlier values +% 'outliers_IX' : a logical array, the +% same size as Y, with +% true values indicating +% outliers +% 'std' : the standard deviations +% +% IOSR.STATISTICS.FUNCTIONALSPREADPLOT methods: +% functionalSpreadPlot - Create the plot. +% +% See also IOSR.STATISTICS.BOXPLOT, IOSR.STATISTICS.QUANTILE, +% IOSR.STATISTICS.FUNCTIONALPLOT, IOSR.STATISTICS.FUNCTIONALBOXPLOT. + + properties (AbortSet) + addPrctiles = [] % Additional percentiles to plot. + addPrctilesLineColor = 'auto' % Colors for the additional percentile lines. + addPrctilesLineStyle = '--' % Styles for the additional percentile lines. + addPrctilesLineWidth = 0.5 % Widths for the additional percentile lines. + innerMode = 'quartile' % Mode of the central shaded area. + limit = '1.5IQR' % Mode indicating the limits that define outliers. + mainMode = 'median' % The statistic used for the central line. + method = 'R-8' % The method used to calculate the quantiles. + outerMode = 'limit' % Mode of the outer lines. + outlierSize = 36 % Size of the outlier markers. + outlierEdgeColor = 'auto' % Color of the outlier marker edges. + outlierFaceColor = 'none' % Color of the outlier marker faces. + outlierMarker = '+' % The outlier marker. + end + + properties (Access = private) + data + end + + methods + + % constructor + function obj = functionalSpreadPlot(varargin) + % FUNCTIONALSPREADPLOT Draw a functional spread plot. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(Y) produces a functional + % spread plot of the data in Y. Y should be an N-by-M or + % N-by-M-by-P array, where N observations for each X value are + % stored in the columns of Y, there are M X-values, and there are + % P functional plots. The plot shows the median as the main line, + % the interquartile range as the shaded region, lines showing the + % limits of the data, and markers showing any outliers. See + % IOSR.STATISTICS.BOXPLOT for an explanation of how limits and + % outliers are estimated. This plot is traditionally known as a + % functional box plot. + % + % Tabular data can be arranged into the appropriate format using + % the IOSR.STATISTICS.TAB2BOX function. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(X,Y) specifies the x-axis + % values for the plot. X should be an M-length vector. The + % default is 1:M. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(...,'PARAMETER',VALUE) + % allows the plotting options to be specified when the plot is + % constructed. + % + % IOSR.STATISTICS.FUNCTIONALSPREADPLOT(AX,...) creates the plot + % in the axes specified by AX. + % + % Examples + % + % Example 1: Draw a functional box plot + % % generate random data + % y = cat(3, randn(100,21), 0.25+randn(100,21)); + % x = 0:20; + % + % % Draw a functional box plot for the first function + % figure + % iosr.statistics.functionalSpreadPlot(x, y(:,:,1)); + % title('Functional box plot.') + % axis tight + % box on + % + % Example 2: Plot means and confidence intervals + % figure + % iosr.statistics.functionalSpreadPlot(x, y,... + % 'spreadAlpha',0.5,... + % 'outerMode', 'none', ... + % 'innermode', 'ci95', ... + % 'mainmode', 'mean', ... + % 'showOutliers', false); + % title('Mean and 95% confidence intervals') + % axis tight + % box on + + start = obj.getXY(varargin{:}); + + % check input is valid size + assert(ndims(obj.y) <= 3 && ndims(obj.y) >= 2, ... + 'iosr:functionalSpreadPlot:invalidY', ... + 'Y must be a two- or three-dimensional array.'); + + % check weights + obj.checkWeights(); + + % set the properties of the plot + obj.setProperties(start,nargin,varargin); + + % remove NaN columns + obj.removeNaN(); + + % calculate the statistics used in the plot + obj.calculateStats(); + + %% draw + + % set handles + obj.parseAxesHandle(varargin{:}); + + % draw the box plot + obj.draw(); + + end + + %% Accessors / Mutators + + function set.mainMode(obj, val) + obj.mainMode = val; + obj.calculateStats(); + obj.draw(); + end + + function set.innerMode(obj, val) + obj.innerMode = val; + obj.calculateStats(); + obj.draw(); + end + + function set.limit(obj, val) + obj.limit = val; + obj.calculateStats(); + obj.draw(); + end + + function set.method(obj, val) + obj.method = val; + obj.calculateStats(); + obj.draw(); + end + + function set.outerMode(obj, val) + obj.outerMode = val; + obj.calculateStats(); + obj.draw(); + end + + % additional percentiles + + function set.addPrctiles(obj, val) + if ~isempty(val) + assert(all(val >= 0) && all(val <= 1000), 'iosr:functionalSpreadPlot:invalidPrctiles', ... + 'Additional percentiles must be in the range [0, 100].') + obj.addPrctiles = val; + end + obj.calculateStats(); + obj.draw(); + end + + function val = get.addPrctilesLineColor(obj) + val = obj.parseColor(obj.addPrctilesLineColor); + end + + function set.addPrctilesLineColor(obj,val) + obj.addPrctilesLineColor = val; + obj.draw(); + end + + function val = get.addPrctilesLineStyle(obj) + val = obj.parseProps(obj.addPrctilesLineStyle, true); + end + + function set.addPrctilesLineStyle(obj,val) + obj.addPrctilesLineStyle = val; + obj.draw(); + end + + function val = get.addPrctilesLineWidth(obj) + val = obj.parseProps(obj.addPrctilesLineWidth, true); + end + + function set.addPrctilesLineWidth(obj,val) + obj.addPrctilesLineWidth = val; + obj.draw(); + end + + % outlier settings + + function set.outlierSize(obj,val) + assert(isnumeric(val) && isscalar(val), 'iosr:functionalSpreadPlot:invalidOutlierSize', ... + '''OUTLIERSIZE'' must be a numeric scalar') + obj.outlierSize = val; + obj.draw(); + end + + function val = get.outlierEdgeColor(obj) + val = obj.parseColor(obj.outlierEdgeColor); + end + + function set.outlierEdgeColor(obj,val) + obj.outlierEdgeColor = val; + obj.draw(); + end + + function val = get.outlierFaceColor(obj) + val = obj.parseColor(obj.outlierFaceColor); + end + + function set.outlierFaceColor(obj,val) + obj.outlierFaceColor = val; + obj.draw(); + end + + function val = get.outlierMarker(obj) + val = obj.parseProps(obj.outlierMarker, false); + end + + function set.outlierMarker(obj,val) + obj.outlierMarker = val; + obj.draw(); + end + + end + + methods (Access = protected) + + % calculate the statistics used in the plot + function calculateStats(obj) + + % Most statistics are calculated in the base class + calculateStats@iosr.statistics.statsPlot(obj); + + % Calculate specific stats + outsize = size(obj.statistics.median); + obj.statistics.addPrctiles = zeros([length(obj.addPrctiles) outsize(2:end)]); + obj.statistics.main = zeros(outsize); + obj.statistics.inner_u = zeros(outsize); + obj.statistics.inner_l = zeros(outsize); + obj.statistics.outer_u = zeros(outsize); + obj.statistics.outer_l = zeros(outsize); + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(obj.outDims) + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = subidx; + subidxAll{1} = ':'; + + if isnumeric(obj.innerMode) + assert(numel(obj.innerMode) == 2, 'iosr:functionalSpreadPlot:invalidInnerMode', ... + 'If numeric, INNERMODE must be a two-element vector.') + obj.statistics.inner_u(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + max(obj.innerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + obj.statistics.inner_l(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + min(obj.innerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + else + assert(ischar(obj.innerMode), 'iosr:functionalSpreadPlot:invalidInnerMode', ... + 'INNERMODE must be numeric or a char array.') + switch obj.innerMode + case 'quartile' + obj.statistics.inner_u(subidx{:}) = obj.statistics.Q3(subidx{:}); + obj.statistics.inner_l(subidx{:}) = obj.statistics.Q1(subidx{:}); + case 'notch' + obj.statistics.inner_u(subidx{:}) = obj.statistics.notch_u(subidx{:}); + obj.statistics.inner_l(subidx{:}) = obj.statistics.notch_l(subidx{:}); + case 'std' + std = obj.statistics.std(subidx{:})/2; + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + std; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - std; + case 'ci90' + cil = ( (1.645 * obj.statistics.std(subidx{:})) / sqrt(obj.statistics.N(subidx{:})) ); + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + cil; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - cil; + case 'ci95' + cil = ( (1.96 * obj.statistics.std(subidx{:})) / sqrt(obj.statistics.N(subidx{:})) ); + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + cil; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - cil; + case 'ci99' + cil = ( (2.576 * obj.statistics.std(subidx{:})) / sqrt(obj.statistics.N(subidx{:})) ); + obj.statistics.inner_u(subidx{:}) = obj.statistics.mean(subidx{:}) + cil; + obj.statistics.inner_l(subidx{:}) = obj.statistics.mean(subidx{:}) - cil; + otherwise + error('iosr:functionalSpreadPlot:unknownInnerMode','Unkonwn INNERMODE.') + end + end + + if isnumeric(obj.outerMode) + assert(numel(obj.outerMode) == 2, 'iosr:functionalSpreadPlot:invalidOuterMode', ... + 'If numeric, OUTERMODE must be a two-element vector.') + obj.statistics.outer_u(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + max(obj.outerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + obj.statistics.outer_l(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}), ... + min(obj.outerMode)/100, [], obj.method, obj.weights(subidxAll{:})); + else + assert(ischar(obj.outerMode), 'iosr:functionalSpreadPlot:invalidOuterMode', ... + 'OUTERMODE must be numeric or a char array.') + switch obj.outerMode + case 'limit' + obj.statistics.outer_u(subidx{:}) = obj.statistics.max(subidx{:}); + obj.statistics.outer_l(subidx{:}) = obj.statistics.min(subidx{:}); + case 'none' + obj.statistics.outer_u(subidx{:}) = NaN; + obj.statistics.outer_l(subidx{:}) = NaN; + otherwise + error('iosr:functionalSpreadPlot:unknownOuterMode','Unknown OUTERMODE.') + end + end + + switch obj.mainMode + case 'mean' + obj.statistics.main(subidx{:}) = obj.statistics.mean(subidx{:}); + case 'median' + obj.statistics.main(subidx{:}) = obj.statistics.median(subidx{:}); + otherwise + error('iosr:functionalSpreadPlot:unknownMainMode','Unknown MAINMODE.') + end + + if ~isempty(obj.addPrctiles) + obj.statistics.addPrctiles(subidxAll{:}) = ... + iosr.statistics.quantile(obj.y(subidxAll{:}),obj.addPrctiles(:)./100,[],obj.method,obj.weights(subidxAll{:})); + end + + temp = obj.y(subidxAll{:}); + obj.statistics.mean(subidx{:}) = mean(temp(~isnan(temp))); + end + + end + + % Draw the plot + function draw(obj) + + if isfield(obj.handles,'axes') + + axes(obj.handles.axes); + cla; + hold on; + + if length(obj.outDims) > 2 + nlines = obj.outDims(3); + else + nlines = 1; + end + + draw@iosr.statistics.functionalPlot(obj); + + for n = nlines:-1:1 + + % draw additional percentiles + if ~isempty(obj.addPrctiles) + for p = 1:numel(obj.addPrctiles) + obj.handles.addPrctiles(p,n) = line(obj.x, squeeze(obj.statistics.addPrctiles(p,:,n)), ... + 'color', obj.addPrctilesLineColor{n}, ... + 'linewidth', obj.addPrctilesLineWidth{n,p}, ... + 'linestyle', obj.addPrctilesLineStyle{n,p}); + end + end + + % draw outliers + if (obj.showOutliers) + xOutliers = repmat(obj.x,size(obj.y, 1), 1); + xOutliers = xOutliers(obj.statistics.outliers_IX(:,:,n)); + yOutliers = obj.y(:,:,n); + yOutliers = yOutliers(obj.statistics.outliers_IX(:,:,n)); + obj.handles.outliers(n) = scatter(xOutliers, yOutliers, ... + obj.outliersize, obj.outlierMarker{n}, ... + 'MarkerEdgeColor', obj.outlierEdgeColor{n}, ... + 'MarkerFaceColor', obj.outlierFaceColor{n}, ... + 'LineWidth', obj.outlierLineWidth{n}); + end + + end + + end + + end + + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/getRmse.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/getRmse.m new file mode 100644 index 0000000000000000000000000000000000000000..4a68d864f1745b0601248f0073e3435f68b4037e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/getRmse.m @@ -0,0 +1,92 @@ +function RMSE = getRmse(X, y, varargin) +%GETRMSE Calculate the root-mean-square error between input data +% +% RMSE = IOSR.STATISTICS.GETRMSE(X, Y) calculates the RMSE of the inputs +% data where +% +% RMSE = sqrt( 1/N-D * SUM(err^2) ) +% err = abs(X-Y) +% +% The input data X and Y can be vectors or matrices; D=1. X and Y must +% have equal size. +% +% RMSE = IOSR.STATISTICS.GETRMSE(X, Y, D) allows the degrees of freedom D +% to be specified. The default is D=1 (you may wish to set it to 0, or +% the degrees of freedom). +% +% RMSEEPS = IOSR.STATISTICS.GETRMSE(X, Y, D, EPSILON) calculates +% epsilon-insensitive RMSE (RMSE*). The parameter EPSILON is a threshold +% for err values: err values less than the respective EPSILON value are +% set to 0; err values greater than EPSILON have EPSILON subtracted from +% them. This allows for the calculation of error 'after' a certain effect +% (such as subjective error). RMSEEPS will ALWAYS be lower than RMSE. The +% value of EPSILON will generally be set to half the 95% confidence +% interval or similar + +% Copyright 2016 University of Surrey. + + % test input types + assert(isnumeric(X)&isnumeric(y),'Input data must be numeric!'); + assert(length(size(X))==length(size(y)),'Input data X and y must be the same size'); + assert(all(size(X)==size(y)),'Input data X and y must be the same size'); + + % extract inputs + nInputs = (numel(varargin) + 2); + d = -1; + epsilon = -1; + epsFlag = 0; + + if nInputs == 2 + if numel(X)>1 + d = 1; + else + error('you should not calculate RMSE for a singular') + end + elseif nInputs == 3 + if ( varargin{1} < numel(X) ) + d = varargin{1}; + else + error('d cannot be larger than or equal to N'); + end + elseif nInputs == 4 + if ( varargin{1} < numel(X) ) + d = varargin{1}; + else + error('d cannot be larger than or equal to N'); + end + if ( varargin{2} >= 0) + epsilon = varargin{2}; + else + error('epsilon should not be negative!'); + end + epsFlag = 1; + elseif (nInputs<2) || (nInputs>4) + error('should be >1 and <5 input arguments') + end + + % Test RMSE == 0 when input vectors identical + assert(Calc(1:10,1:10,1,0,0)==0,'RMSE of x=Y for equal vectors does not compute correctly'); + assert(Calc(ones(3,3,3),ones(3,3,3),1,0,0)==0,'RMSE of x=Y for equal matrices does not compute correctly'); + + % Test RMSE calculated properly for dummy data + assert(Calc([1 2 3; 1 2 3; 1 2 3],[3 2 1; 3 2 1; 3 2 1],1,0,0)==(sqrt(3)),'RMSE of x=Y for dummy data does not compute correctly'); + + % Test RMSEeps calculated properly for dummy data + assert(single(Calc([1 2 3],[1.4 2.4 3.4],1,0.3,1))==single(sqrt(0.015)),'RMSE epsilon insensitive for dummy data does not compute correctly'); + assert(single(Calc([1 2 3],[1.4 2.4 3.4],1,[0.3 0.4 0.4],1))==single(sqrt(0.005)),'RMSE epsilon insensitive for dummy data does not compute correctly'); + + RMSE = Calc(X,y,d,epsilon,epsFlag); + +end + +function RMSE = Calc(X,y,d,epsilon,epsFlag) +%CALC Calculate RMSE & RMSE* + + % Calculate RMSE + err = abs(X-y); + if epsFlag + err = max(err-epsilon,0); + end + RMSE = sqrt((1/(numel(err)-d)) * sum(err(:).^2)); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/kernelDensity.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/kernelDensity.m new file mode 100644 index 0000000000000000000000000000000000000000..86b108437f35a241704adec8fa7954436d6d4e2e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/kernelDensity.m @@ -0,0 +1,152 @@ +function [d, xd, bw] = kernelDensity(x, bins, h, kernel) +%KERNELDENSITY Calculate the kernel density of a data set +% +% [D, XD] = IOSR.STATISTICS.KERNELDENSITY(X) calculate the kernel density +% D of a dataset X for query points XD. The kernel density is calculated +% for 100 query points equally spaced between the minimum and maximum of +% the data X. The density is estimated using a gaussian kernel with a +% width that is optimal for normal data. X may be a vector, matrix, or +% multi-dimensional array; the entire array is treated as the sample. D +% and XD are 100-point column vectors. NaN are excluded from the +% calculations. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS) calculates the density for +% the query points specified by BINS. If BINS is a scalar, then BINS +% points are queried between MIN(X(:)) and MAX(X(:)); if BINS is a +% vector, then the values are used as the query points directly. D and XD +% are column vectors. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, H) uses the bandwidth H to +% calculate the kernel density. H must be a scalar. BINS may be an empty +% array in order to use the default described above. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, [], KERNEL) uses the +% kernel function specified by KERNEL to calculate the density. The +% kernel may be: +% - 'normal' (default), +% - 'uniform', +% - 'triangular', +% - 'epanechnikov', +% - 'quartic', +% - 'triweight', +% - 'tricube', +% - 'cosine', +% - 'logistic', +% - 'sigmoid', or +% - 'silverman'. +% For the uniform case the bandwidth is set to 15% of the range of the +% data [1]. Otherwise the bandwidth is chosen to be optimal for normal +% data assuming a gaussian kernel. +% +% ... = IOSR.STATISTICS.KERNELDENSITY(X, BINS, H, KERNEL) allows the +% bins BINS and bandwidth H to be specified directly. +% +% [D, XD, BW] = IOSR.STATISTICS.KERNELDENSITY(...) returns the badwidth +% BW. +% +% Examples +% +% Example 1: Plot the kernel density of gaussian data +% figure +% % gaussian random numbers +% y = randn(100000, 1); +% % density +% [d, xd] = iosr.statistics.kernelDensity(y); +% % plot +% plot(xd, d); +% +% Example 2: Density trace with 200 bins of width of 10% of data range +% figure +% % random numbers +% y = randn(100000, 1); +% % y range +% range = max(y(:)) - min(y(:)); +% % density trace +% [d, xd] = iosr.statistics.kernelDensity(y, 200, 0.1*range, 'uniform'); +% % plot +% plot(xd, d); +% +% References +% +% [1] Hintze, Jerry L.; Nelson, Ray D. (1998). "Violin Plots: A Box +% Plot-Density Trace Synergism". The American Statistician. 52 (2): +% 181?4. + + %% input check + + x = x(:); + x = x(~isnan(x)); + assert(numel(x) > 1, 'X must be a vector, matrix, or array.') + + % x bins + if nargin < 2 + bins = []; + end + if isempty(bins) + bins = 100; + end + if isscalar(bins) + bins = linspace(min(x), max(x), round(bins)); + end + bins = bins(:); + + % bin width + if nargin < 3 + h = []; + end + + % kernel + if nargin < 4 + kernel = []; + end + if isempty(kernel) + kernel = 'normal'; + end + % return kernel function + switch lower(kernel) + case 'uniform' + K = @(u) 0.5*(abs(u) <= 1); + if isempty(h) + h = 0.15 * (max(x) - min(x)); + end + case 'normal' + K = @(u) ((1/sqrt(2*pi)) * exp(-0.5*(u.^2))); + case 'triangular' + K = @(u) ((1-abs(u)) .* (abs(u) <= 1)); + case 'epanechnikov' + K = @(u) ((0.75*(1-(u.^2))) .* (abs(u) <= 1)); + case 'quartic' + K = @(u) (((15/16)*(1-(u.^2)).^2) .* (abs(u) <= 1)); + case 'triweight' + K = @(u) (((35/32)*(1-(u.^2)).^3) .* (abs(u) <= 1)); + case 'tricube' + K = @(u) (((70/81)*(1-(abs(u).^3)).^3) .* (abs(u) <= 1)); + case 'cosine' + K = @(u) (((pi/4)*cos((pi/2)*u)) .* (abs(u) <= 1)); + case 'logistic' + K = @(u) (1 / (exp(u) + 2 + exp(-u))); + case 'sigmoid' + K = @(u) ((2/pi) * (1 / (exp(u) + exp(-u)))); + case 'silverman' + K = @(u) (0.5 * exp((-abs(u))/(sqrt(2))) .* sin((abs(u))/(sqrt(2)) + (pi/4))); + otherwise + error('Unknown kernel specified'); + end + if isempty(h) + h = ((4*(std(x).^5))/(3*numel(x))).^(1/5); + end + + assert(isscalar(h), 'h must be a scalar') + + %% calculate kernel density + + xd = sort(bins); + d = zeros(size(xd)); + + for i = 1:numel(xd) + d(i) = sum(K((x-xd(i))/h))./(numel(x)*h); + end + d(isnan(d)) = 0; + bw = h; + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/laprnd.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/laprnd.m new file mode 100644 index 0000000000000000000000000000000000000000..969e59a1845bb35cc351b9104809638614603c05 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/laprnd.m @@ -0,0 +1,38 @@ +function r = laprnd(varargin) +%LAPRND Pseudorandom numbers drawn from the Laplace distribution +% +% R = IOSR.STATISTICS.LAPRND(N) returns an N-by-N matrix containing +% pseudorandom values drawn from the Laplace distribution with mean = 0 +% and standard deviation = 1. +% +% IOSR.STATISTICS.LAPRND(M,N) or IOSR.STATISTICS.LAPRND([M,N]) returns an +% M-by-N matrix. +% +% IOSR.STATISTICS.LAPRND(M,N,P,...) or +% IOSR.STATISTICS.LAPRND([M,N,P,...]) returns an M-by-N-by-P-by-... +% array. +% +% IOSR.STATISTICS.LAPRND returns a scalar. +% +% IOSR.STATISTICS.LAPRND(SIZE(A)) returns an array the same size as A. +% +% Note: The size inputs M, N, P, ... should be nonnegative integers. +% Negative integers are treated as 0. +% +% The sequence of numbers produced by LAPRND is determined by the +% settings of the uniform random number generator that underlies RAND, +% RANDI, and RANDN. Control that shared random number generator using +% RNG. +% +% See also IOSR.STATISTICS.TRIRND, RAND, RANDN, RANDI, RNG. + +% Based on code (Matlab FE File ID: #13705) written by Elvis Chen, 2007. + +% Copyright 2016 University of Surrey. + + % Generate Laplacian noise + u = rand(varargin{:})-0.5; + b = 1/sqrt(2); + r = -b*sign(u).*log(1-(2*abs(u))); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/qqPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/qqPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..ea289df2e911b87cd776251bdec057d030546ddd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/qqPlot.m @@ -0,0 +1,173 @@ +function h = qqPlot(varargin) +%QQPLOT Quantile-quantile plot with patch option +% +% IOSR.STATISTICS.QQPLOT(Y) displays a quantile-quantile plot of the +% sample quantiles of Y versus theoretical quantiles from a normal +% distribution. If the distribution of Y is normal, the plot will be +% close to linear. +% +% IOSR.STATISTICS.QQPLOT(X,Y) displays a quantile-quantile plot of two +% samples. If the samples come from the same distribution, the plot will +% be linear. +% +% The inputs X and Y should be numeric and have an equal number of +% elements; every element is treated as a member of the sample. +% +% The plot displays the sample data with the plot symbol 'x'. +% Superimposed on the plot is a dashed straight line connecting the first +% and third quartiles. +% +% IOSR.STATISTICS.QQPLOT(...,MODE) allows the appearance of the plot to +% be configured. With MODE='line' (default), the plot appears as +% described above. With MODE='patch', the data are plotted as a patch +% object, with the area bound by the x-distribution and the linear fit +% shaded grey. With mode='both' the two appearances are combined. +% +% IOSR.STATISTICS.QQPLOT(...,MODE,METHOD) and +% IOSR.STATISTICS.QQPLOT(...,[],METHOD) allows the method for calculating +% the quartiles, used for the fit line, to be specified. The default is +% 'R-8'. Type 'help iosr.statistics.quantile' for more information. The +% latter form of the function call uses the default mode. +% +% H = IOSR.STATISTICS.QQPLOT(...) returns a two- or three-element vector +% of handles to the plotted object. The nature of the handles depends +% upon the mode. In all cases, the first handle is to the sample data, +% the second handle is to the fit line. With MODE='patch' or MODE='both', +% there is third handle to the patch object. +% +% Example +% +% % Display Q-Q plots for the rand and randn functions +% figure +% subplot(2,1,1) +% iosr.statistics.qqPlot(rand(20),'patch') +% subplot(2,1,2) +% h = iosr.statistics.qqPlot(randn(20),'patch'); +% set(h(3),'FaceColor','r') % change fill color +% +% See also IOSR.STATISTICS.QUANTILE, IOSR.STATISTICS.BOXPLOT. + +% Copyright 2016 University of Surrey. + + %% determine X and Y + + IXn = cellfun(@(x) isnumeric(x) & ~isempty(x),varargin); + + switch sum(IXn) + case 0 + error('iosr:qqPlot:noData','No input data specified') + case 1 + % compare to normal distrbution + Y = get_input_sample(varargin,IXn); + p = (.5:length(Y))/length(Y); + X = sqrt(2)*erfinv(2*p - 1); + x_label = 'Standard normal quantiles'; + y_label = 'Sample quantiles'; + case 2 + % compare to input data distribution + Y = get_input_sample(varargin,find(IXn,1,'last')); + X = get_input_sample(varargin,find(IXn,1,'first')); + assert(isequal(size(X),size(Y)), 'iosr:quantile:invalidInput', 'Input data must be the same size') + x_label = 'X quantiles'; + y_label = 'Y quantiles'; + otherwise + error('iosr:qqPlot:unkonwnInput','Unknown input specified') + end + + %% determine mode and method + + % find inputs + IXc = cellfun(@(x) ischar(x) | isempty(x),varargin); + switch sum(IXc) + case 0 + mode = []; + method = []; + case 1 + mode = varargin{IXc}; + method = []; + case 2 + mode = varargin{find(IXc,1,'first')}; + method = varargin{find(IXc,1,'last')}; + otherwise + error('iosr:qqPlot:unknownString','Unknown string specified') + end + + % defaults + if isempty(mode) + mode = 'line'; + end + if isempty(method) + method = 'R-8'; + end + + %% calculate fit to first and third quartile + + % quartiles + q1x = iosr.statistics.quantile(X,.25,[],method); + q3x = iosr.statistics.quantile(X,.75,[],method); + q1y = iosr.statistics.quantile(Y,.25,[],method); + q3y = iosr.statistics.quantile(Y,.75,[],method); + + % slope + slope = (q3y-q1y)./(q3x-q1x); + centerx = (q1x+q3x)/2; + centery = (q1y+q3y)/2; + + % fit + maxx = max(X); + minx = min(X); + maxy = centery + slope.*(maxx - centerx); + miny = centery - slope.*(centerx - minx); + + % lines + X_fit = linspace(minx,maxx,length(X)); + Y_fit = linspace(miny,maxy,length(X)); + + %% plot data + + hold on + + if strcmpi(mode,'patch') || strcmpi(mode,'both') + Hp = patch([X fliplr(X_fit)],[Y fliplr(Y_fit)],[0.5 0.5 0.5]); + set(Hp,'edgecolor','none') + else + Hp = NaN; + end + + switch lower(mode) + case 'line' + linestyle = 'xk'; + case 'patch' + linestyle = '-k'; + case 'both' + linestyle = 'xk'; + otherwise + error('iosr:qqPlot:unknownMode','Unknown mode specified') + end + + H = plot(X,Y,linestyle,X_fit,Y_fit,'--k'); + + hold off + + % axis labels + xlabel(x_label) + ylabel(y_label) + + box on; axis tight + set(gca,'layer','top') + + % return handle + if nargout>0 + h = H; + if isobject(Hp) || ishandle(Hp) + h = [h; Hp]; + end + end + +end + +function Z = get_input_sample(z,IX) +%GET_INPUT_SAMPLE get sample, order, and convert to vector + Z = z{IX}; + Z = sort(Z(:))'; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/quantile.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/quantile.m new file mode 100644 index 0000000000000000000000000000000000000000..9ea308228318bebd69947f227e4b9148fb08d46e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/quantile.m @@ -0,0 +1,234 @@ +function [q,N] = quantile(X,p,dim,method,weights) +%QUANTILE Quantiles of a sample via various methods. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P) returns quantiles of the values in X. +% P is a scalar or a vector of cumulative probability values. When X is +% a vector, Q is the same size as P, and Q(i) contains the P(i)-th +% quantile. When X is a matrix, the i-th row of Q contains the P(i)-th +% quantiles of each column of X. For N-D arrays, +% IOSR.STATISTICS.QUANTILE operates along the first non-singleton +% dimension. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,DIM) calculates quantiles along +% dimension DIM. The DIM'th dimension of Q has length LENGTH(P). +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,DIM,METHOD) calculates quantiles using +% one of the methods described in http://en.wikipedia.org/wiki/Quantile. +% The method are designated 'R-1'...'R-9'; the default is R-8 as +% described in http://bit.ly/1kX4NcT, whereas Matlab uses 'R-5'. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,[],METHOD) uses the specified METHOD, +% but calculates quantiles along the first non-singleton dimension. +% +% Q = IOSR.STATISTICS.QUANTILE(X,P,[],METHOD,WEIGHTS) and +% IOSR.STATISTICS.QUANTILE(X,P,[],[],WEIGHTS) uses the array WEIGHTS to +% weight the values in X when calculating quantiles. If no weighting is +% specified, the method determines the real-valued index in to the data +% that is used to calculate the P(i)-th quantile. When a weighting array +% WEIGHTS is specified (WEIGHTS should be the same size as X), this index +% is mapped to the cumulative weights (the weights are scaled to sum to +% N(i) - see below), and a new weighted index is returned (using linear +% interpolation) for the point where the cumulative weights equal the +% unweighted index. The weighted index is used to calculate the P(i)-th +% quantile. If the values in WEIGHTS are equal, then the weighted and +% unweighted index (and correpsonding quantile) are identical. The +% default method R-8 is used if METHOD is specified as an empty array +% ([]). +% +% [Q,N] = IOSR.STATISTICS.QUANTILE(...) returns an array that is the same +% size as Q such that N(i) is the number of points used to calculate +% Q(i). +% +% Further reading +% +% Hyndman, R.J.; Fan, Y. (November 1996). "Sample Quantiles in +% Statistical Packages". The American Statistician 50 (4): 361-365. +% Frigge, Michael; Hoaglin, David C.; Iglewicz, Boris (February 1989). +% "Some Implementations of the Boxplot". The American Statistician 43 +% (1): 50-54. +% +% See also QUANTILE. + +% Copyright 2016 University of Surrey. + + %% Check input and make default assignments + + assert(isnumeric(X), 'iosr:quantile:invalidX', 'X must be a numeric'); + assert(isvector(p) & isnumeric(p), 'iosr:quantile:invalidP', 'P must be a numeric vector'); + assert(all(p>=0 & p<=1), 'iosr:quantile:invalidP', 'Values in P must be in the interval [0,1].') + + if nargin<2 + error('iosr:quantile:tooFewInputArgs','Not enough input arguments.') + end + + dims = size(X); + if nargin<3 || isempty(dim) + dim = find(dims>1,1,'first'); % default dim + else % validate input + assert(isnumeric(dim) | isempty(dim), 'iosr:quantile:invalidDim', 'DIM must be an integer or empty'); + assert(isint(dim) | isempty(dim), 'iosr:quantile:invalidDim', 'DIM must be an integer or empty'); + assert(dim>0, 'iosr:quantile:invalidDim', 'DIM must be greater than 0') + end + + if nargin<4 + method = 'r-8'; % default method + else % validate input + if isempty(method) + method = 'r-8'; % default method + else + assert(ischar(method), 'iosr:quantile:invalidMethod', 'METHOD must be a character array') + end + end + + if nargin<5 + weights = []; + else + assert(isequal(size(X),size(weights)) || isempty(weights), 'iosr:quantile:invalidWeights', 'WEIGHTS must be the same size as X'); + end + + %% choose method + + % See http://en.wikipedia.org/wiki/Quantile#Estimating_the_quantiles_of_a_population + + switch lower(method) + case 'r-1' + min_con = @(N,p)(p==0); + max_con = @(N,p)(false); + h = @(N,p)((N*p)+.5); + Qp = @(x,h)(x(ceil(h-.5))); + case 'r-2' + min_con = @(N,p)(p==0); + max_con = @(N,p)(p==1); + h = @(N,p)((N*p)+.5); + Qp = @(x,h)((x(ceil(h-.5))+x(floor(h+.5)))/2); + case 'r-3' + min_con = @(N,p)(p<=(.5/N)); + max_con = @(N,p)(false); + h = @(N,p)(N*p); + Qp = @(x,h)(x(round(h))); + case 'r-4' + min_con = @(N,p)(p<(1/N)); + max_con = @(N,p)(p==1); + h = @(N,p)(N*p); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-5' + min_con = @(N,p)(p<(.5/N)); + max_con = @(N,p)(p>=((N-.5)/N)); + h = @(N,p)((N*p)+.5); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-6' + min_con = @(N,p)(p<(1/(N+1))); + max_con = @(N,p)(p>=(N/(N+1))); + h = @(N,p)((N+1)*p); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-7' + min_con = @(N,p)(false); + max_con = @(N,p)(p==1); + h = @(N,p)(((N-1)*p)+1); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-8' + min_con = @(N,p)(p<((2/3)/(N+(1/3)))); + max_con = @(N,p)(p>=((N-(1/3))/(N+(1/3)))); + h = @(N,p)(((N+(1/3))*p)+(1/3)); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + case 'r-9' + min_con = @(N,p)(p<((5/8)/(N+.25))); + max_con = @(N,p)(p>=((N-(3/8))/(N+.25))); + h = @(N,p)(((N+.25)*p)+(3/8)); + Qp = @(x,h)(x(floor(h)) + ((h-floor(h))*(x(floor(h)+1)-x(floor(h))))); + otherwise + error('iosr:quantile:unknownMethod',['Method ''' method ''' does not exist']) + end + + %% calculate quartiles + + % reshape data so function works down columns + order = mod(dim-1:dim+length(dims)-2,length(dims))+1; + dims_shift = dims(order); + x = rearrange(X,order,[dims_shift(1) prod(dims_shift(2:end))]); + if ~isempty(weights) + weights = rearrange(weights,order,[dims_shift(1) prod(dims_shift(2:end))]); + cumwfunc = @accumulateWeights; + wfunc = @weightedIndex; + else + cumwfunc = @(~,~,~,N) 1:N; + wfunc = @(x,~) x; + end + + % pre-allocate q + q = zeros([length(p) prod(dims_shift(2:end))]); + N = zeros([length(p) prod(dims_shift(2:end))]); + for m = 1:length(p) + for n = 1:numel(q)/length(p) + [xSorted,ind] = sort(x(~isnan(x(:,n)),n)); % sort + N(m,n) = length(xSorted); % sample size + k = cumwfunc(weights,ind,n,N(m,n)); + switch N(m,n) + case 0 + q(m,n) = NaN; + case 1 + q(m,n) = xSorted; + otherwise + if min_con(N(m,n),p(m)) % at lower limit + q(m,n) = xSorted(1); + elseif max_con(N(m,n),p(m)) % at upper limit + q(m,n) = xSorted(N(m,n)); + else % everything else + huw = h(N(m,n),p(m)); % unweighted index + hw = wfunc(huw,k); + q(m,n) = Qp(xSorted,hw); + end + end + end + end + + % restore dims of q to equate to those of input + q = irearrange(q,order,[length(p) dims_shift(2:end)]); + N = irearrange(N,order,[length(p) dims_shift(2:end)]); + + % if q is a vector, make same shape as p + if numel(p)==numel(q) + q=reshape(q,size(p)); + N=reshape(N,size(p)); + end + +end + +function cumweights = accumulateWeights(weights,ind,n,N) +%ACCUMULATEWEIGHTS accumulate the weights + + wSorted = weights(ind,n); % sort weights + wSorted = wSorted*N/sum(wSorted); % normalize weights to sum to N + cumweights = cumsum(wSorted); % cumulative weights + +end + +function hw = weightedIndex(huw, cumweights) +%WEIGHTEDINDEX calculate index from cumulative weights + + ii = find(sign(cumweights-huw)<0,1,'last'); + jj = find(sign(cumweights-huw)>0,1,'first'); + if isempty(ii) || isempty(jj) + hw = huw; + else + hw = ii + (huw-cumweights(ii))/(cumweights(jj)-cumweights(ii)); % weighted index + end + +end + +function y = isint(x) +%ISINT check if input is whole number + y = x==round(x); +end + +function y = rearrange(x,order,shape) +%REARRANGE reshape and permute to make target dim column + y = permute(x,order); + y = reshape(y,shape); +end + +function y = irearrange(x,order,shape) +%IREARRANGE reshape and permute to original size + y = reshape(x,shape); + y = ipermute(y,order); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/statsPlot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/statsPlot.m new file mode 100644 index 0000000000000000000000000000000000000000..fe5e73ae77169f3c8d1c7851fdac88356e16132b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/statsPlot.m @@ -0,0 +1,232 @@ +classdef (Abstract, CaseInsensitiveProperties = true) statsPlot < ... + matlab.mixin.SetGet +%STATSPLOT An abstract superclass for classes that plot statistics +% +% As an abstract class, this class cannot be instantiated. It provides no +% public methods. The class is a super class for: +% - iosr.statistics.boxPlot +% - iosr.statistics.functionalPlot + + properties (AbortSet) + handles = struct % Structure containing handles to plot objects. + end + + properties (SetAccess = protected) + x % The x data. + y % The y data. + weights = []; % The weights for y. + statistics = struct % Structure containing the statistics used for the plot. + end + + properties (Access = protected) + outDims % dimensions of output + ydims % dimensions of y + end + + properties (SetAccess = protected, Dependent, Hidden) + axes = [] % The parent axes of the plot. + fig = [] % The parent figure of the plot. + end + + methods + + % these are all deprecated and the handles moved to the obj.handles struct + + function val = get.axes(obj) + warning('iosr:statsPlot:deprecatedProp','''obj.axes'' is deprecated. Use ''obj.handles.axes'' instead.'); + val = obj.handles.axes; + end + + function val = get.fig(obj) + warning('iosr:statsPlot:deprecatedProp','''obj.fig'' is deprecated. Use ''obj.handles.fig'' instead.'); + val = obj.handles.fig; + end + + end + + methods (Access = protected) + + % set plot properties + function setProperties(obj,start,ngin,vgin) + + % read parameter/value inputs + if start < ngin % if parameters are specified + nArgs = length(vgin)-start+1; + if round(nArgs/2)~=nArgs/2 + error('iosr:statsPlot:nameValuePairs','Properties must be propertyName/propertyValue pairs') + end + % overwrite defults + for pair = reshape(vgin(start:end),2,[]) % pair is {propName;propValue} + obj.(pair{1}) = pair{2}; + end + end + + end + + function axSet = parseAxesHandle(obj, varargin) + ax = []; + axValid = false; + axSet = false; + if ((isscalar(varargin{1}) && ishghandle(varargin{1},'axes')) ... + || isa(varargin{1},'matlab.graphics.axis.AbstractAxes')) + axSet = true; + ax = handle(varargin{1}); + if isvalid(varargin{1}(1)) + axValid = true; + end + end + if nargout < 1 + if axSet + if axValid + obj.handles.axes = ax; + axes(obj.handles.axes); %#ok<CPROPLC> + obj.handles.fig = ancestor(obj.handles.axes, 'figure'); + else + error('iosr:statsPlot:axisInvalid','Axes handle is invalid.') + end + else + obj.handles.axes = newplot; + obj.handles.fig = gcf; + end + end + end + + % Get X and Y data from input + function start = getXY(obj,varargin) + + if length(varargin) > 1 + axSet = obj.parseAxesHandle(varargin{:}); + if axSet + skip = 1; + else + skip = 0; + end + if isnumeric(varargin{2+skip}) + obj.x = varargin{1+skip}; + obj.y = varargin{2+skip}; + start = 3+skip; + else + obj.y = varargin{1+skip}; + obj.x = 1:size(obj.y,2); + start = 2+skip; + end + else + obj.y = varargin{1}; + obj.x = 1:size(obj.y,2); + start = 1; + end + + if size(obj.y,1)==1 + error('iosr:statsPlot:invalidInput','Data are plotted for each column. Each column in the input has only one data point.') + end + + % check x/y data + assert(isvector(obj.x), 'iosr:statsPlot:invalidX', 'x must be a vector'); + assert(isnumeric(obj.y), 'iosr:statsPlot:invalidY', 'y must be a numeric column vector or matrix'); + assert(numel(obj.x)==size(obj.y,2), 'iosr:statsPlot:invalidInput', 'x must have the same number of elements as y has columns') + + % size of input + obj.ydims = size(obj.y); + obj.outDims = obj.ydims; obj.outDims(1) = 1; + + if length(obj.outDims) < 3 + obj.outDims = [obj.outDims 1]; + end + + end + + % Check the weights are the correct size, or set the weights to 1 + % if no weights are provided + function checkWeights(obj) + + if isempty(obj.weights) + obj.weights = ones(size(obj.y)); + else + assert(isequal(size(obj.y),size(obj.weights)), 'iosr:statsPlot:invalidWeights', 'weights must be the same size as y') + end + + end + + % Remove NaNs + function removeNaN(obj) + + % remove NaN columns + if isnumeric(obj.x) + obj.x = obj.x(~isnan(obj.x)); + obj.y = obj.y(:,~isnan(obj.x),:); + obj.y = reshape(obj.y,obj.ydims); + if ~isempty(obj.weights) + obj.weights = obj.weights(:,~isnan(obj.x),:); + obj.weights = reshape(obj.weights,obj.ydims); + end + end + + end + + % calculate the statistics for the plot + function calculateStats(obj) + + % calculate stats + obj.statistics.median = iosr.statistics.quantile(obj.y,.5,[],obj.method,obj.weights); % median + outsize = size(obj.statistics.median); + obj.statistics.mean = zeros(outsize); % sample mean + obj.statistics.std = zeros(outsize); % sample standard deviation + obj.statistics.N = zeros(outsize); % sample size + obj.statistics.Q1 = zeros(outsize); % lower quartile + obj.statistics.Q3 = zeros(outsize); % upper quartile + obj.statistics.IQR = zeros(outsize); % inter-quartile range + obj.statistics.notch_u = zeros(outsize); % high notch value + obj.statistics.notch_l = zeros(outsize); % low notch value + obj.statistics.min = zeros(outsize); % minimum (excluding outliers) + obj.statistics.max = zeros(outsize); % maximum (excluding outliers) + subidx = cell(1,length(obj.outDims)); + for n = 1:prod(obj.outDims) + [subidx{:}] = ind2sub(obj.outDims, n); + subidxAll = subidx; + subidxLogical = subidx; + subidxAll{1} = ':'; + [~,obj.statistics.N(subidx{:})] = iosr.statistics.quantile(obj.y(subidxAll{:}),0.25,[],obj.method,obj.weights(subidxAll{:})); + temp = obj.y(subidxAll{:}); + weights_temp = obj.weights(subidxAll{:}); + ix = ~isnan(temp) & ~isnan(weights_temp); + temp = temp(ix); + weights_temp = weights_temp(ix); + weights_temp = weights_temp./sum(weights_temp); + obj.statistics.mean(subidx{:}) = sum(temp .* weights_temp); + obj.statistics.std(subidx{:}) = std(temp); + obj.statistics.Q1(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),0.25,[],obj.method,obj.weights(subidxAll{:})); + obj.statistics.Q3(subidx{:}) = iosr.statistics.quantile(obj.y(subidxAll{:}),0.75,[],obj.method,obj.weights(subidxAll{:})); + obj.statistics.IQR(subidx{:}) = obj.statistics.Q3(subidx{:})-obj.statistics.Q1(subidx{:}); + obj.statistics.notch_u(subidx{:}) = obj.statistics.median(subidx{:})+(1.58*obj.statistics.IQR(subidx{:})/sqrt(obj.statistics.N(subidx{:}))); + obj.statistics.notch_l(subidx{:}) = obj.statistics.median(subidx{:})-(1.58*obj.statistics.IQR(subidx{:})/sqrt(obj.statistics.N(subidx{:}))); + if isnumeric(obj.limit) + upper_limit = iosr.statistics.quantile(obj.y(subidxAll{:}),max(obj.limit)/100,[],obj.method,obj.weights(subidxAll{:})); + lower_limit = iosr.statistics.quantile(obj.y(subidxAll{:}),min(obj.limit)/100,[],obj.method,obj.weights(subidxAll{:})); + else + switch lower(obj.limit) + case '1.5iqr' + upper_limit = obj.statistics.Q3(subidx{:})+1.5*obj.statistics.IQR(subidx{:}); + lower_limit = obj.statistics.Q1(subidx{:})-1.5*obj.statistics.IQR(subidx{:}); + case '3iqr' + upper_limit = obj.statistics.Q3(subidx{:})+3*obj.statistics.IQR(subidx{:}); + lower_limit = obj.statistics.Q1(subidx{:})-3*obj.statistics.IQR(subidx{:}); + case 'none' + upper_limit = Inf; + lower_limit = -Inf; + otherwise + error('iosr:statsPlot:unknownLimit','Unknown ''limit'': ''%s''',obj.limit) + end + end + obj.statistics.outliers_IX(subidxAll{:}) = obj.y(subidxAll{:})>upper_limit | obj.y(subidxAll{:})<lower_limit; + subidxLogical{1} = ~obj.statistics.outliers_IX(subidxAll{:}); + obj.statistics.min(subidx{:}) = min(min(obj.y(subidxLogical{:})),obj.statistics.Q1(subidx{:})); % min excl. outliers but not greater than lower quartile + obj.statistics.max(subidx{:}) = max(max(obj.y(subidxLogical{:})),obj.statistics.Q3(subidx{:})); % max excl. outliers but not less than upper quartile + subidxLogical{1} = obj.statistics.outliers_IX(subidxAll{:}); + obj.statistics.outliers{subidx{:}} = obj.y(subidxLogical{:}); + end + + end + + end + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/tab2box.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/tab2box.m new file mode 100644 index 0000000000000000000000000000000000000000..89ff2471d2fa856e5b975e37bc11f930680bf8f9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/tab2box.m @@ -0,0 +1,171 @@ +function [y,x,g] = tab2box(Xin,Yin,Gin) +%TAB2BOX Prepare tabular data for boxPlot function +% +% Y = IOSR.STATISTICS.TAB2BOX(XIN,YIN) prepares data, in tabular form, +% for use in the BOX_PLOT function. Specifically, XIN and YIN are vectors +% (for example column vectors from a results table). Y is an N-by-P +% numeric array, where P is the number of unique elements in XIN, and N +% is the maximum number of occurences of any individual element of XIN. +% In cases where elements in XIN do not occur an equal number of times, +% columns in YIN are padded with NaNs. +% +% Y = IOSR.STATISTICS.TAB2BOX(XIN,YIN,GIN) returns an +% N-by-P-by-G-by-I-by-J... numeric array, where G is the number of unique +% elements in the first column of GIN, I is the number of unique elements +% in the second column of GIN, etc. GIN is a numeric or cell matrix with +% as many rows as XIN or YIN. The input facilitates hierarchical grouping +% of the data in the box plot, with the grouping order determined by the +% column order of GIN. +% +% [Y,X] = IOSR.STATISTICS.TAB2BOX(...) returns the unique values in XIN +% to X. +% +% [Y,X,G] = IOSR.STATISTICS.TAB2BOX(...) returns the unique values in GIN +% to G. G is a cell vector whereby the Nth element contains a vector of +% length SIZE(Y,N+2). +% +% Example +% +% % Prepare data for box_plot grouped by two variables +% +% % load data +% % (requires Statistics or Machine Learning Toolbox) +% load carbig +% +% % arrange data +% [y,x,g] = iosr.statistics.tab2box(Cylinders,MPG,when); +% +% % sort +% IX = [1 3 2]; % order +% g = g{1}(IX); +% y = y(:,:,IX); +% +% % plot +% figure +% h = iosr.statistics.boxPlot(x,y,... +% 'boxColor','auto','medianColor','k',... +% 'scalewidth',true,'xseparator',true,... +% 'groupLabels',g,'showLegend',true); +% box on +% title('MPG by number of cylinders and period') +% xlabel('Number of cylinders') +% ylabel('MPG') +% +% See also IOSR.STATISTICS.BOXPLOT. + +% Copyright 2016 University of Surrey. + + %% validate input + + % validate Xin + if ischar(Xin) + Xin = cellstr(Xin); + end + assert(isvector(Xin), 'iosr:tab2box:invalidInput', 'Xin must be a vector') + + % validate Yin + assert(isvector(Yin), 'iosr:tab2box:invalidInput', 'Yin must be a vector') + assert(isnumeric(Yin), 'iosr:tab2box:invalidInput', 'Yin must be numeric') + + % validate Gin + if nargin<3 + Gin = []; + else + if ischar(Gin) + Gin = cellstr(Gin); + end + assert(isvector(Gin) || size(Gin,1)==numel(Yin), 'iosr:tab2box:invalidInput', 'Gin must be a vector or a matrix with as many rows as Y has elements.') + if isvector(Gin) + Gin = Gin(:); + end + end + + %% group + + % unique values + x = getUniques(Xin); + if iscell(x) + x = x{1}; + end + g = getUniques(Gin); + if ~iscell(g) + temp = cell(1,size(g,2)); + for c = 1:size(g,2); + temp{c} = g(:,c); + end + g = temp; + end + + % preallocate cell array + gdims = cellfun(@length,g); + dims = [1,length(x),gdims]; + yc = cell(dims); + subgidx = cell(1,length(gdims)); + + % put data into cells + for a = 1:length(x) + IXx = findIX(Xin,x,a); + for b = 1:prod(gdims) + [subgidx{:}] = ind2sub(gdims, b); % get group index + subidx = [{1} {a} subgidx{:}]; % make main index + IXg = true(size(Xin)); % select everything at first + for c = 1:length(subgidx) % narrow it down + IXg = IXg & findIX(Gin(:,c),g{c},subgidx{c}); + end + % return y as column + yc{subidx{:}} = reshape(Yin(IXx & IXg),sum(IXx & IXg),1); + end + end + + %% convert to numeric array + + try % see if can concat directly + y = cell2mat(yc); + catch % else pad with NaNs + maxSizeY = max(cellfun(@length,yc(:))); + for a = 1:numel(yc) + if length(yc{a}) < maxSizeY + yc{a} = [yc{a}; NaN(maxSizeY-length(yc{a}),1)]; + end + end + y = cell2mat(yc); + end + +end + +function IX = findIX(L,l,n) +%FINDIX find entry in array from lookup array and index + + if iscellstr(L) + IX = strcmp(L,l{n}); + elseif iscell(L) + IX = cell2mat(L)==l(n); + else + IX = L==l(n); + end +end + +function out = getUniques(d) +%GETUNIQUES return unique entries from vector + + if isvector(d) % ensure column vector + d = d(:); + end + dims = zeros(1,size(d,2)); + u = cell(1,size(d,2)); + % put unique values into columns + for c = 1:size(d,2) + if iscellstr(d(:,c)) || isnumeric(d(:,c)) + u{c} = unique(d(:,c)); + else + u{c} = unique(cell2mat(d(:,c))); + end + dims(c) = length(u{c}); + end + try % to make a numeric array + out = cell2mat(u); + catch % keep as cell array + out = u; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/trirnd.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/trirnd.m new file mode 100644 index 0000000000000000000000000000000000000000..9ecfb15a4dc44091c984741b164a8a2ab6aa2b0a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+statistics/trirnd.m @@ -0,0 +1,38 @@ +function r = trirnd(varargin) +%TRIRND Pseudorandom numbers drawn from the triangular distribution +% +% R = IOSR.STATISTICS.TRIRND(N) returns an N-by-N matrix containing +% pseudorandom values drawn from the triangular distribution constrained +% to (-1,1) and mode = 0. +% +% IOSR.STATISTICS.TRIRND(M,N) or IOSR.STATISTICS.TRIRND([M,N]) returns an +% M-by-N matrix. +% +% IOSR.STATISTICS.TRIRND(M,N,P,...) or +% IOSR.STATISTICS.TRIRND([M,N,P,...]) returns an M-by-N-by-P-by-... +% array. +% +% IOSR.STATISTICS.TRIRND returns a scalar. +% +% TRIRND(SIZE(A)) returns an array the same size as A. +% +% Note: The size inputs M, N, P, ... should be nonnegative integers. +% Negative integers are treated as 0. +% +% The sequence of numbers produced by TRIRND is determined by the +% settings of the uniform random number generator that underlies RAND, +% RANDI, and RANDN. Control that shared random number generator using +% RNG. +% +% See also IOSR.STATISTICS.LAPRND, RAND, RANDN, RANDI, RNG. + +% Based on code (Matlab FE File ID: #13705) written by Elvis Chen, 2007. + +% Copyright 2016 University of Surrey. + + % Generate traingular noise + u1 = rand(varargin{:})-0.5; + u2 = rand(varargin{:})-0.5; + r = u1+u2; + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/buildSvnProfile.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/buildSvnProfile.m new file mode 100644 index 0000000000000000000000000000000000000000..0544208b56b69b810606bebace6ec91094a23a2c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/buildSvnProfile.m @@ -0,0 +1,109 @@ +function [svn_profile,svn_str] = buildSvnProfile(folders,keywords,strs,rec) +%BUILDSVNPROFILE Read data from files tagged with SVN keywords +% +% This function extracts SVN keyword data from specified files, and +% returns the filename, path and keyword data to a cell array (and +% optional char array). +% +% Keyword data are placed in files automatically by Subversion at each +% commit using the 'keyword' function. The data can be useful in +% maintaining an audit trail, or establishing the version used to +% generate a particular set of results. +% +% SVN_PROFILE = IOSR.SVN.BUILDSVNPROFILE(FOLDERS,KEYWORDS) returns a cell +% array SVN_PROFILE containing data associated with the SVN keywords +% KEYWORDS. The function will search through files contained in folders. +% +% SVN_PROFILE is a two dimensional cell array; there is one row for each +% file found in FOLDERS, and N columns: one each for the full path for +% the file, and appended columns for each specified keyword in KEYWORDS. +% Data are only returned for files that contain the specified keyword(s). +% An empty cell array, 0-by-2, is returned if no keywords are found. +% +% SVN_PROFILE = IOSR.SVN.BUILDSVNPROFILE(FOLDERS,KEYWORDS,STRS) allows +% additional filter strings STRS to be specified. See +% IOSR.GENERAL.GETCONTENTS for details of permitted filter strings. +% +% ... = IOSR.SVN.BUILDSVNPROFILE(FOLDERS,KEYWORDS,STRS,REC), with REC = +% true, allows folders to be searched recursively (default is false). +% +% [SVN_PROFILE,SVN_STR] = IOSR.SVN.BUILDSVNPROFILE(...) outputs a char +% array SVN_STR of the profile, with columns concatenated to produce +% continuous lines. Spaces are inserted to ensure that columns are +% aligned (in a monospaced font). The array is appropriate for printing +% or writing to a text file, for example. The char array can be written +% to a text file with the following command: +% +% dlmwrite('svn_profile.txt',svn_str,'delimiter','') +% +% FOLDERS, KEYWORDS,and STRS may be a char array specifying a single +% occurrence, or a cell array of strings specifying multiple occurrences. +% +% See also IOSR.SVN.READSVNKEYWORD, IOSR.GENERAL.GETCONTENTS. + +% Copyright 2016 University of Surrey. + + if ischar(folders) + folders = cellstr(folders); + end + + if ischar(keywords) + keywords = cellstr(keywords); + end + + if nargin > 2 + if ischar(strs) + strs = cellstr(strs); + end + else + strs = {'files'}; + end + + % add subfolders if recursion is requested + if nargin > 3 + if rec + for f = folders + folders = [folders; iosr.general.getContents(char(f),'filter','folders','rec',true,'path','full')]; %#ok<AGROW> + end + end + end + + keydata = cell(0,1+length(keywords)); % empty cell array to be appended + n = 1; + for f = 1:length(folders) + folder = folders{f}; + for s = 1:length(strs) + str = strs{s}; + [files,dirflag] = iosr.general.getContents(folder,'filter',str,'path','full'); % find relevant files + files = files(~dirflag); % ignore directories + if ~isempty(files) + for h = 1:length(files) + file = files{h}; + % extract keyword data from file + for k = 1:length(keywords) + keyword = keywords{k}; + keydata{n,1} = file; + keydata{n,1+k} = iosr.svn.readSvnKeyword(file,keyword); + end + n = n+1; + end + end + end + end + + % remove files where no keyword is found + IX = true(size(keydata(:,2))); + for k = 1:length(keywords) + IX = IX & cellfun(@isempty,keydata(:,1+k)); + end + svn_profile = keydata(~IX,:); + + % Build char array version of data + space = repmat(' ',size(svn_profile(:,1))); % spaces to insert between columns + svn_str = char(svn_profile(:,1)); % first column (file path) + % append keyword columns: + for k = 1:length(keywords) + svn_str = [svn_str space char(svn_profile(:,1+k))]; %#ok<AGROW> + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/headRev.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/headRev.m new file mode 100644 index 0000000000000000000000000000000000000000..371430c5f64e5f191de345081007fb8645bdfa7e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/headRev.m @@ -0,0 +1,82 @@ +function [rev,file] = headRev(folders,strs,rec) +%HEADREV Retrieve the head revision for specified files +% +% This function finds the most recently committed file in the specified +% folders(s) and returns its revision and filename. The files must +% contain the 'Revision' and 'Date' keywords. +% +% REV = IOSR.SVN.HEADREV(FOLDERS) returns the head revision (i.e. the +% highest revision) for all files in FOLDERS. +% +% REV = IOSR.SVN.HEADREV(FOLDERS,STRS) allows additional filter strings +% STRS to be specified. See GETCONTENTS for details of permitted filter +% strings. +% +% REV = IOSR.SVN.HEADREV(FOLDERS,STRS,REC), with REC = true, allows +% folders to be searched recursively (default is false). +% +% [REV,FILE] = IOSR.SVN.HEADREV(...) returns the filename to FILE of the +% file with the highest revision. +% +% FOLDERS and STRS may be a string specifying a single occurrence, or a +% cell array of strings specifying multiple occurrences. This function +% requires that the 'Revision' keyword is used in the searched functions. +% +% Note that if the folders include files from an externally-defined +% repository (which has been updated more recently than the native +% repository), a misleading revision number may be presented. +% +% See also IOSR.GENERAL.GETCONTENTS, IOSR.SVN.BUILDSVNPROFILE, +% IOSR.SVN.READSVNKEYWORD. + +% Copyright 2016 University of Surrey. + + keyword = 'Date'; % use this data to sort files (doubtful that any others would work, without considerable parsing) + + if ischar(folders) + folders = cellstr(folders); + end + + if nargin > 1 + if ischar(strs) + strs = cellstr(strs); + end + if isempty(strs) + strs = {'files'}; + end + else + strs = {'files'}; + end + + % add subfolders if recursion is requested + if nargin > 2 + if rec + for f = folders + folders = [folders; iosr.general.getContents(char(f),'filter','folders','rec',true,'path','full')]; %#ok<AGROW> + end + end + end + + % get revision info for files + svn_profile = iosr.svn.buildSvnProfile(folders,keyword,strs); + + % remove the keyword and convert revision strings to numbers + svn_profile(:,2) = cellfun(@(x) (x(length(keyword)+3:end)),svn_profile(:,2),'uni',false); + + % remove NaN (files that don't have the revision keyword) + IX1 = cellfun(@isempty,svn_profile(:,2)); + svn_profile = svn_profile(~IX1,:); + + % sort by revision number + [~,IX2] = sort(svn_profile(:,2)); + svn_profile = svn_profile(IX2,:); + + % get highest revision number + rev = iosr.svn.readSvnKeyword(svn_profile{end,1},'Revision'); + + % return corresponding filename, if requested + if nargout>1 + file = svn_profile{end,1}; + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/readSvnKeyword.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/readSvnKeyword.m new file mode 100644 index 0000000000000000000000000000000000000000..97e86a012486cf4b586ea89e3c58b3a7ac5728e1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/+svn/readSvnKeyword.m @@ -0,0 +1,59 @@ +function keydata = readSvnKeyword(filename,keyword,crop) +%READSVNKEYWORD Read data from a file tagged with an SVN keyword +% +% The function takes an input filename and searches that file for a +% Subversion keyword. The data associated with the keyword are returned +% in a character array. Keyword data are placed in files automatically by +% Subversion at each commit using the 'keyword' function. The data can be +% useful in maintaining an audit trail, or establishing the version used +% to generate a particular set of results. +% +% KEYDATA = IOSR.SVN.READSVNKEYWORD(FILENAME,KEYWORD) returns a string +% KEYDATA containing data associated with the SVN keyword KEYWORD in a +% file specified by FILENAME. +% +% FILENAME and KEYWORD must be strings specifying a single file and +% keyword respectively. To read multiple files or use multiple keywords, +% use BUILD_SVN_PROFILE instead. The function returns an empty string if +% the keyword is not found. +% +% KEYDATA = IOSR.SVN.READSVNKEYWORD(FILENAME,KEYWORD,CROP), with CROP = +% true (default is false), removes the keyword, and leading and trailing +% spaces, from the returned string. +% +% See also IOSR.SVN.BUILDSVNPROFILE. + +% Copyright 2016 University of Surrey. + + + assert(ischar(filename) & ischar(keyword), 'iosr:readSvnKeyword:invalidInputs', 'FILENAME and KEYWORD must be char arrays') + + if nargin < 3 + crop = false; + end + + keydata = ''; + + fid = fopen(filename); % open file + assert(fid~=-1, 'iosr:readSvnKeyword:invalidFile', ['read_svn_keyword: ''' filename ''' not found']) + + tline = fgetl(fid); % read first line + while ischar(tline) + k1 = strfind(tline,['$' keyword ':']); % find keyword + if ~isempty(k1) % if it is found + k2 = strfind(tline,'$'); % find the end of the keyword data + k2 = k2(k2>k1); + keydata = tline(k1+1:k2-2); % extract the data from the line + tline = -1; % set tline to numeric + else + tline = fgetl(fid); % read next line + end + end + + if crop + keydata = keydata(find(isspace(keydata),1,'first')+1:end); + end + + fclose(fid); % close file + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/Contents.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/Contents.m new file mode 100644 index 0000000000000000000000000000000000000000..426bbfadea3996d0bc278cad1e32465891918b32 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/Contents.m @@ -0,0 +1,98 @@ +% +IOSR +% +% Contents file for +IOSR and its subfolders. +% +% +IOSR +% iosr.install - Set search paths, and download and install dependencies +% +% +IOSR/+ACOUSTICS +% iosr.acoustics.irStats - Calculate RT, DRR, Cte, and EDT for impulse response file +% iosr.acoustics.rtEst - Estimate reverberation time based on room size and absorption +% +% +IOSR/+AUDITORY +% iosr.auditory.azimuth2itd - Convert azimuth in degrees to ITD +% iosr.auditory.binSearch - Conduct a binary search +% iosr.auditory.calcIld - Calculate normalised interaural level difference +% iosr.auditory.chXcorr - Calculate cross-correlograms with a wide range of options +% iosr.auditory.chXcorr2 - Calculate cross-correlograms with a range of options +% chXcorr2_c.c +% chXcorr_c.c +% iosr.auditory.createWindow - Create a Hann or exp. window with specified onsets/offsets +% iosr.auditory.dupWeight - Calculate duplex weighting coefficients for ITD and ILD +% iosr.auditory.erbRate2hz - Convert ERB rate to Hz +% iosr.auditory.freqMulti - Calculate frequency coefficient for ITD-azimuth warping +% iosr.auditory.gammatoneFast - Produce an array of responses from gammatone filters via FFT +% iosr.auditory.hz2erbRate - Convert Hz to ERB rate +% iosr.auditory.iso226 - ISO 226:2003 Normal equal-loudness-level contours +% iosr.auditory.itd2azimuth - Convert ITD to azimuth +% iosr.auditory.lindemannInh - Signal pre-processing for Lindemann's cross-correlation +% iosr.auditory.loudWeight - Calculate loudness weighting coefficients +% iosr.auditory.makeErbCFs - Make a series of center frequencies equally spaced in ERB-rate +% iosr.auditory.meddisHairCell - Calculate Ray Meddis' hair cell model for a number of channels +% iosr.auditory.perceptualCentroid - Perceptual spectral centroid +% iosr.auditory.perceptualCentroid2 - Alternative perceptual spectral centroid +% iosr.auditory.xcorrLindemann - Cross-correlation based on Lindemann's precedence model +% xcorrLindemann_c.c +% +% +IOSR/+BSS +% iosr.bss.applyIdealMasks - Calculate and apply ideal masks via STFT +% iosr.bss.applyMask - Apply a time-frequency mask to an STFT +% iosr.bss.calcImr - Calculates the Ideal Mask Ratio (IMR) +% iosr.bss.calcSnr - Calculate the separation SNR +% iosr.bss.cfs2fcs - Calculate gammatone crossover frequencies +% iosr.bss.example - Determine STFT parameters +% iosr.bss.generateMixtures - Generate arrays of mixtures from targets and interferers +% iosr.bss.getFullMask - Convert frame rate mask to a sample-by-sample mask +% iosr.bss.idealMasks - Calculate ideal time-frequency masks from STFTs +% iosr.bss.mixture - Class of sound source separation mixture +% iosr.bss.resynthesise - Resynthesise a target from a time-frequency mask +% iosr.bss.source - Class of sound source separation source +% +% +IOSR/+DSP +% iosr.dsp.audio - Abstract superclass providing audio-related properties and methods +% iosr.dsp.autocorr - Perform autocorrelation via FFT +% iosr.dsp.convFft - Convolve two vectors using FFT multiplication +% iosr.dsp.istft - Calculate the Inverse Short-Time Fourier Transform +% iosr.dsp.lapwin - Laplace window +% iosr.dsp.localpeaks - Find local peaks and troughs in a vector +% iosr.dsp.ltas - Calculate the long-term average spectrum of a signal +% iosr.dsp.matchEQ - Match the LTAS of a signal to an arbitrary spectral magnitude +% iosr.dsp.rcoswin - Raised cosine window +% iosr.dsp.rms - Calculate the rms of a vector or matrix +% iosr.dsp.sincFilter - Apply a near-ideal low-pass or band-pass brickwall filter +% iosr.dsp.smoothSpectrum - Apply 1/N-octave smoothing to a frequency spectrum +% iosr.dsp.stft - Calculate the short-time Fourier transform of a signal +% iosr.dsp.vsmooth - Smooth a vector using mathematical functions +% +% +IOSR/+FIGURES +% iosr.figures.chMap - Create a monochrome-compatible colour map +% iosr.figures.cmrMap - Create a monochrome-compatible colour map +% iosr.figures.multiwaveplot - Stacked line plots from a matrix or vectors +% iosr.figures.subfigrid - Create axis positions for subfigures +% +% +IOSR/+GENERAL +% iosr.general.cell2csv - Output a cell array to a CSV file +% iosr.general.checkMexCompiled - Check if mex file is compiled for system +% iosr.general.getContents - Get the contents of a specified directory +% iosr.general.updateContents - Create a Contents.m file including subdirectories +% iosr.general.urn - Generate random number sequence without duplicates +% +% +IOSR/+STATISTICS +% iosr.statistics.boxPlot - Draw a box plot +% iosr.statistics.functionalBoxPlot - Draw a functional boxplot +% iosr.statistics.functionalPlot - Abstract superclass for functional plots +% iosr.statistics.functionalSpreadPlot - Draw a functional plot showing data spread +% iosr.statistics.getRmse - Calculate the root-mean-square error between input data +% iosr.statistics.laprnd - Pseudorandom numbers drawn from the Laplace distribution +% iosr.statistics.qqPlot - Quantile-quantile plot with patch option +% iosr.statistics.quantile - Quantiles of a sample via various methods +% iosr.statistics.statsPlot - An abstract superclass for classes that plot statistics +% iosr.statistics.tab2box - Prepare tabular data for boxPlot function +% iosr.statistics.trirnd - Pseudorandom numbers drawn from the triangular distribution +% +% +IOSR/+SVN +% iosr.svn.buildSvnProfile - Read data from files tagged with SVN keywords +% iosr.svn.headRev - Retrieve the head revision for specified files +% iosr.svn.readSvnKeyword - Read data from a file tagged with an SVN keyword +% +% This file was generated by updateContents.m on 31 May 2017 at 17:06:32. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/install.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/install.m new file mode 100644 index 0000000000000000000000000000000000000000..deacd6312ab065a2e39eee203b2869f509e94260 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/+iosr/install.m @@ -0,0 +1,52 @@ +function mypath = install +%INSTALL Set search paths, and download and install dependencies. +% +% IOSR.INSTALL downloads and installs the toolbox dependencies. The +% function also adds the required paths to the Matlab search path. +% +% MYPATH = IOSR.INSTALL returns the old Matlab search path MYPATH. + +% Copyright 2016 University of Surrey. + + %% download and install SOFA + + % install dir + currdir = cd; + cd([fileparts(which(mfilename('fullpath'))) filesep '..']); + directory = pwd; + sofa_folder = [directory filesep 'deps' filesep 'SOFA_API']; + + if ~(exist(sofa_folder,'dir') == 7) + % download and install + sofa_filename = 'sofa-api.zip'; + try % Sourceforge location changes from time to time + websave(sofa_filename,'http://vorboss.dl.sourceforge.net/project/sofacoustics/sofa-api-mo-1.0.2.zip'); + catch % Fall back to development release on GitHub + display('Warning: Failed to download SOFA v1.0.2 from Sourceforge, downloading development release...') + websave(sofa_filename,'https://github.com/sofacoustics/API_MO/archive/master.zip'); + end + unzip(sofa_filename,sofa_folder); + movefile([sofa_folder filesep 'API_MO' filesep '*'],[sofa_folder filesep]); + + % clean up + delete(sofa_filename) + rmdir([sofa_folder filesep 'doc' filesep],'s') + rmdir([sofa_folder filesep 'HRTFs' filesep],'s') + rmdir([sofa_folder filesep 'API_MO' filesep],'s') + else + display(strcat('Found existing SOFA directory: ', sofa_folder)) + end + + %% Add directories to path + + cd(directory); + mypath = addpath(directory,... + [directory filesep 'deps' filesep 'SOFA_API']); + + %% start SOFA + + SOFAstart(0); + + cd(currdir); % return to original directory + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/.gitignore b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..e56622b5b9e28e99a03ee8a2bbef807cf8394a03 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/.gitignore @@ -0,0 +1,6 @@ +# compiled binary +*.mex* + +# temp files +*.m~ +*.c~ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/LICENSE b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..a3ab3106d3b2d64f6d4b2b70f54ad86433132555 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Institute of Sound Recording + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/README.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/README.md new file mode 100644 index 0000000000000000000000000000000000000000..90c482ecc2288b591bd477223e1760c9724a75f4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/README.md @@ -0,0 +1,44 @@ +# IoSR Matlab Toolbox + +A general purpose Matlab toolbox containing functions and classes for: auditory modelling, signal processing, sound source separation, statistics, plotting, etc. See [Contents.m](https://github.com/IoSR-Surrey/Toolbox/blob/master/+iosr/Contents.m) for a full list of functions/classes. + +## Installation + +Basic installation only requires you to add the install directory to the Matlab search path. + +If you wish to perform certain audio / signal processing tasks (especially spatialisation), please navigate to the install directory and type + +``` +iosr.install +``` + +This will automatically download the toolbox's dependencies for these tasks, and add the necessary paths to your search path. + +## Usage + +Use these functions as: + +``` +iosr.<folderName>.<functionName>(<args>) +``` + +(Ignoring the '+' in the folder name.) Alternatively, use the `import` directive to add one or more namespaces, e.g.: + +``` +import iosr.auditory +import iosr.* +``` + +If using `import`, note that some function names may conflict with built-in Matlab function names (e.g. `quantile`). One method of resolving the conflict and shortening the function call is to create a handle to any functions with conflicting names, e.g. + +``` +qntl = @iosr.statistics.quantile; +``` + +Type + +``` +help iosr +``` + +for more information. \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/.gitignore b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..60e13b6534e1783a891f11edb50cec1cfe106572 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/.gitignore @@ -0,0 +1,29 @@ +# compiled convention files +/SOFAtoolbox/conventions/*.mat +/SOFAtoolbox/conventions/*.txt +# test files for demos +/SOFAtoolbox/demos/*.sofa +/SOFAtoolbox/demos/demo_FreeFieldHRTF/*.fig +/SOFAtoolbox/demos/demo_FreeFieldHRTF/*.png +/SOFAtoolbox/demos/LigetiHall_CubeletToSt450/ +/SOFAtoolbox/test/*.sofa +/SOFAtoolbox/test/*/*.wav +/SOFAtoolbox/test/LigetiHall_CubeletToSt450/ +/data/ARI/*/*.mat +/data/BTDEI/*/*/*/*/*/*.mat +/data/BTDEI/*/headphones_info.mat +/data/CIPIC/*/*.mat +/data/CIPIC/show_data/ +/data/CIPIC/CIPIC_hrtf_database/ +/data/FHK/*.mat +/data/IEM/*.wav +/data/IEM/*.pdf +/data/LISTEN/IRC_1002/ +/data/MIT KEMAR/full/*/*.wav +/data/Oldenburg/HRIR_database_mat/ +/data/SCUT/nearfield/ +/data/SOFA/sofatoolbox_test/*.sofa +/data/SOFA/database/*/*.sofa +/data/SOFA/headphones/*/*.sofa +/data/TU-Berlin KEMAR/*.mat +/SOFAtoolbox/helpers/*.m diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/README.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a9b1f711153bd443cad060444125bb484ecb0f27 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/README.md @@ -0,0 +1,64 @@ +SOFA - Spatially Oriented Format for Acoustics +============================================== + +SOFA is a file format for reading, saving, and describing spatially +oriented data of acoustic systems. + +Examples of data we consider are head-related transfer functions (HRTFs), +binaural room impulse responses (BRIRs), multichannel measurements such as done +with microphone arrays, or directionality data of loudspeakers. + +The format specification is the major focus of SOFA, but we also aim in providing +toolboxes for reading and writing the data in SOFA. For more information on the +format specifications and available data, see http://www.sofaconventions.org/. + +This project implements a reference toolbox for SOFA: The SOFA Toolbox. + +SOFA Toolbox 2.x implements SOFA versions 2.x. The SOFA Toolbox has been previously +known as the SOFA API_MO, which supported SOFA versions up to 1.x. + + +Downloads +========= + +Current releases of SOFA Toolbox can be found on its [old +home](http://sourceforge.net/projects/sofacoustics/files/?source=navbar). + +**Note:** +- The currently latest release is known as the SOFA API M/O version 1.1.3. +- The SOFA Toolbox 2.0 has never been released. +- The SOFA Toolbox 2.1 is currently under preparation. It will support SOFA 2.1 as known as AES69-2022. + + +Usage +===== + +## Matlab/Octave + +In order to use SOFA with Matlab or Octave add its `SOFAtoolbox` folder +to your search paths. After that you can play around with your acoustic measurements +as shown by the following example which uses a HRTF measurement. + +```matlab +%% put your information here: +hrtf = SOFAload('path/to_your/HRTF.sofa'); +soundInput = audioread('path/to_your/fancy_audio_file.wav'); + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(hrtf.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); +``` diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..dda2380db8f49f5f33175cf59d42dd0b3c23be07 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m @@ -0,0 +1,61 @@ +function Obj = SOFAaddVariable(Obj,Name,Dim,Value) +%SOFAaddVariable +% Obj = SOFAaddVariable(Obj,Name,Dim,Value) adds a user-defined variable +% to the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). DIM is a string +% describing the dimensions of the variable according to SOFA specifications. +% The content of NAME is stored in VALUE which must be of the size DIM. +% The used-defined variable NAME will be stored as Obj.NAME and its +% dimension will be stored as Obj.API.Dimensions.NAME. Note that user- +% defined variables can be saved in SOFA file and thus remain in the +% object when loaded from a SOFA file. +% +% Obj = SOFAaddVariable(Obj,Name,'PRIVATE',Value) adds a private variable +% to OBJ. The private variable NAME will be stored as Obj.PRIVATE.NAME. +% Note that the private variables will be not stored in SOFA files and +% arbitrary dimensions are allowed. +% +% Note that adding variables to Data is not supported and should not be used +% as it might be confusing having user-defined variables in a Data structure. +% Consider adding a variable at the global level instead, which would be more +% clear for others. + +% #Author: Piotr Majdak +% #Author: Piotr Majdak: dimension is added if not previously found. (9.8.2014) +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAaddVariable +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Dim=upper(Dim); +switch Dim + case 'PRIVATE' + Obj.PRIVATE.(Name)=Value; + otherwise + switch Name + case {'API','PRIVATE','GLOBAL'} + error('This variable name is reserved.'); + otherwise + if strncmp(Name,'Data.',length('Data.')) + % add variable to Data + Name=Name(length('Data.')+1:end); + Obj.Data.(Name)=Value; + Obj.API.Dimensions.Data.(Name)=Dim; + else + % add variable to root + Obj.(Name)=Value; + Obj.API.Dimensions.(Name)=Dim; + end + dims=SOFAdefinitions('dimensions'); + for ii=1:length(Dim) + if ~isfield(dims,Dim(ii)) + error('Dimension not supported.'); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m new file mode 100644 index 0000000000000000000000000000000000000000..4cd1e5367374580beb8290071fd3c9d3099dca5e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m @@ -0,0 +1,27 @@ +function output = SOFAappendText(Obj,attribute,new) +%SOFAappendText +% +% output = SOFAappendText(Obj,attribute,new) appends the new text to the +% attribute (as string) using the correct SOFA separators. If the attribute is empty +% or non-existing, the output will be the new text only. +% +% example: +% Obj.GLOBAL_Title = SOFAappendText(Obj, 'GLOBAL_Title', 'Append me to the title.'); + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAappendText +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~isfield(Obj,attribute), Obj.(attribute)=''; end +if isempty(Obj.(attribute)), + output=new; +else + output=[Obj.(attribute) SOFAdefinitions('EOL') new]; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m new file mode 100644 index 0000000000000000000000000000000000000000..7699a5664ee60e26c72ffdf90259d9f72db1aa2c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m @@ -0,0 +1,273 @@ +function [flags,keyvals,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun) +%SOFAARGHELPER Parse arguments for SOFA +% Usage: [flags,keyvals,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun); +% +% Input parameters: +% posdepnames : Names of the position dependant parameters. +% definput : Struct to define the allowed input +% arglist : Commandline of the calling function (varargin) +% callfun : Name of calling function (optional) +% +% Output parameters: +% flags : Struct with information about flags. +% keyvals : Struct with key / values. +% varargout : The position dependant pars. properly initialized +% +% [flags,keyvals,varargout]=SOFAarghelper(posdepnames,definput,arglist,callfun) assists in +% parsing input parameters for a function. Parameters come in +% four categories: +% +% Position dependant parameters. These must not be strings. These are +% the first parameters passed to a function, and they are really just a short way +% of specifying key/value pairs. See below. +% +% Flags. These are single string appearing after the position dependant +% parameters. +% +% Key/value pairs. The key is always a string followed by the value, which can be +% anything. +% +% Expansions. These appear as flags, that expand into a pre-defined list of parameters. +% This is a short-hand way of specifying standard sets of flags and key/value pairs. +% +% The parameters are parsed in order, so parameters appearing later in varargin will override +% previously set values. +% +% The following example for calling SOFAARGHELPER is taken from DGT: +% +% definput.keyvals.L=[]; +% definput.flags.phase={'freqinv','timeinv'}; +% [flags,kv]=SOFAarghelper({'L'},definput,varargin); +% +% The first line defines a key/value pair with the key 'L' having an initial value of `[]` +% (the empty matrix). +% +% The second line defines a group of flags by the name of phase. The +% group phase contains the flags `'freqinv'` and `'timeinv'`, which can +% both be specified on the command line by the user. The group-name +% phase is just for internal use, and does not appear to the user. The +% flag mentioned first in the list will be selected by default, and only +% one flag in a group can be selected at any time. A group can contain as +% many flags as desired. +% +% The third line is the actual call to SOFAARGHELPER which defines the +% output flags and `kv`. The input `{'L'}` indicates that the value of +% the parameter 'L' can also be given as the very first value in +% varargin. +% +% The output struct kv contains the key/value pairs, so the value associated to `'L'` is +% stored in kv.L. +% +% The output struct flags contains information about the flags choosen +% by the user. The value of flags.phase will be set to the selected flag +% in the group phase and additionally, the value of `flags.do_timeinv` +% will be 1 if 'timeinv' was selected and 0 otherwise, and similarly for +% 'freqinv'. This allows for easy checking of selected flags. +% + +% #Author: Peter L. Soendergaard, Copyright (C) 2005-2012 +% #Author: Piotr Majdak: Modified from the LTFAT 1.1.2 for SOFA by Piotr Majdak. +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. + +persistent SOFA_CONF; + +if isempty(SOFA_CONF) + SOFA_CONF.fundefs = struct; +end; + +if ischar(posdepnames) + % Special interface needed for ltfatsetdefaults and ltfatgetdefaults, + % activated when first argument is a string. + + % First input argument, posdepnames, is a string, one of the options + % in the "switch" section below + % Second input argument, definput, is a function name to get or set + % Third input argument, arglist , is a cell-array with options to set. + + switch(lower(posdepnames)) + case 'get' + if isfield(SOFA_CONF.fundefs,definput) + flags=SOFA_CONF.fundefs.(definput); + else + flags={}; + end; + case 'set' + SOFA_CONF.fundefs.(definput)=arglist; + case 'all' + flags=SOFA_CONF.fundefs; + case 'clearall' + SOFA_CONF.fundefs=struct; + end; + return +end; + +if nargin<4 + f=dbstack; + callfun=f(2).name; +end; + +nposdep=numel(posdepnames); + +% Resolve import specifications BEFORE adding our own specifications. +if isfield(definput,'import') + for imp = definput.import; + definput=feval(['arg_',imp{1}],definput); + end; +end; + +if isfield(definput,'flags') + defflags=definput.flags; +else + defflags=struct; +end; + +if isfield(definput,'keyvals') + defkeyvals=definput.keyvals; +else + defkeyvals=struct; +end; + +if isfield(definput,'groups') + groups=definput.groups; +else + groups=struct; +end; + +total_args = numel(arglist); + +% Determine the position of the first optional argument. +% If no optional argument is given, return nposdep+1 +first_str_pos = 1; +while first_str_pos<=total_args && ~ischar(arglist{first_str_pos}) + first_str_pos = first_str_pos +1; +end; + +% If more than nposdep arguments are given, the first additional one must +% be a string +if (first_str_pos>nposdep+1) + error('%s: Too many input arguments',upper(callfun)); +end; + +n_first_args=min(nposdep,first_str_pos-1); + +keyvals=defkeyvals; + +% Copy the given first arguments +for ii=1:n_first_args + keyvals.(posdepnames{ii})=arglist{ii}; +end; + +% Initialize the position independent parameters. +% and create reverse mapping of flag -> group +flagnames=fieldnames(defflags); +flags=struct; +% In order for flags to start with a number, it is necessary to add +% 'x_' before the flag when the flags are used a field names in +% flagreverse. Externally, flags are never used a field names in +% structs, so this is an internal problem in ltfatarghelper that is +% fixed this way. +flagsreverse=struct; +for ii=1:numel(flagnames) + name=flagnames{ii}; + flaggroup=defflags.(name); + flags.(name)=flaggroup{1}; + for jj=1:numel(flaggroup) + flagsreverse.(['x_', flaggroup{jj}])=name; + flags.(['do_',flaggroup{jj}])=0; + end; + flags.(['do_',flaggroup{1}])=1; +end; + +%Get the rest of the arguments +restlist = arglist(first_str_pos:end); + +%Check for default arguments +if isfield(SOFA_CONF.fundefs,callfun) + s=SOFA_CONF.fundefs.(callfun); + restlist=[s,restlist]; +end; + +% Check for import defaults +if isfield(definput,'importdefaults') + % Add the importdefaults before the user specified arguments. + restlist=[definput.importdefaults,restlist]; +end; + +while ~isempty(restlist) + argname=restlist{1}; + restlist=restlist(2:end); % pop + found=0; + + % Is this name a flag? If so, set it + if isfield(flagsreverse,['x_',argname]) + % Unset all other flags in this group + flaggroup=defflags.(flagsreverse.(['x_',argname])); + for jj=1:numel(flaggroup) + flags.(['do_',flaggroup{jj}])=0; + end; + + flags.(flagsreverse.(['x_',argname]))=argname; + flags.(['do_',argname])=1; + found=1; + end; + + % Is this name the key of a key/value pair? If so, set the value. + if isfield(defkeyvals,argname) + keyvals.(argname)=restlist{1}; + restlist=restlist(2:end); + found=1; + end; + + % Is this name a group definition? If so, put the group in front of the parameters + if isfield(groups,argname) + s=groups.(argname); + restlist=[s,restlist]; + found=1; + end; + + % Is the name == 'argimport' + if strcmp('argimport',argname) + fieldnames_flags= fieldnames(restlist{1}); + fieldnames_kvs = fieldnames(restlist{2}); + for ii=1:numel(fieldnames_flags) + importname=fieldnames_flags{ii}; + flags.(importname)=restlist{1}.(importname); + end; + for ii=1:numel(fieldnames_kvs) + importname=fieldnames_kvs{ii}; + keyvals.(importname)=restlist{2}.(importname); + end; + restlist=restlist(3:end); + found=1; + end; + + if found==0 + if ischar(argname) + error('%s: Unknown parameter: %s',upper(callfun),argname); + else + error('%s: Parameter is not a string, it is of class %s',upper(callfun),class(argname)); + end; + end; + + %ii=ii+1; +end; + +% Fill varargout + +varargout=cell(1,nposdep); +for ii=1:nposdep + varargout(ii)={keyvals.(posdepnames{ii})}; +end; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m new file mode 100644 index 0000000000000000000000000000000000000000..bb8c5816c4caf6be538d13a9b96d809a1323411f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m @@ -0,0 +1,76 @@ +function ApparentPositionVector = SOFAcalculateAPV(Obj) +%SOFAcalculateAPV +% ApparentPositionVector = SOFAcalculateAPV(Obj) calculates the apparent position vector +% (ApparentPositionVector) which represents the position of the source relative to the +% listener's position and view. ApparentPositionVector is in the format [azi ele radius] +% with units [deg deg m]. +% Note that ListenerUp is not considered and the ApparentPositionVector can be considered as +% the HRTF direction usually used in HRTF databases + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAcalculateAPV +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% === Apparent azimuth === +% Apparent azimuth is the relative direction of the sound source in the +% horizontal plane from the listener viewpoint +% +% Get head orientation of the listener and source position in spherical +% coordinates +HeadOrientation = SOFAconvertCoordinates( ... + Obj.ListenerView,Obj.ListenerView_Type,'spherical'); +SourcePosition = SOFAconvertCoordinates( ... + Obj.SourcePosition,Obj.SourcePosition_Type,'spherical'); +% Calculate the relative azimuth angle between them +APVazimuth = correctAzimuth(bsxfun( ... + @minus,SourcePosition(:,1),HeadOrientation(:,1))); + +% === Apparent elevation === +% Apparent elevation is the relative direction of the sound source in the median +% plane from the listener viewpoint +APVelevation = correctElevation(bsxfun( ... + @minus,SourcePosition(:,2),HeadOrientation(:,2))); + +% === Apparent distance === +% Apparent distance is the relative distance between the sound source and the +% listener +% +% Get listener positon in spherical coordinates +ListenerPosition = SOFAconvertCoordinates( ... + Obj.ListenerPosition,Obj.ListenerPosition_Type,'spherical'); +% Relative distance +APVdistance = bsxfun(@minus,SourcePosition(:,3),ListenerPosition(:,3)); + +% Combine to matrix +ApparentPositionVector = [ ... + APVazimuth, ... + APVelevation, ... + APVdistance, ... +]; + +end + +function phi = correctAzimuth(phi) + % Ensure -360 <= phi <= 360 + phi = rem(phi,360); + % Ensure -180 <= phi < 180 + phi(phi<-180) = phi(phi<-180) + 360; + phi(phi>=180) = phi(phi>=180) - 360; +end + +% TODO: check what convetion we are using for delta! +function delta = correctElevation(delta) + % Ensure -180 <= delta <= 180 + delta = correctAzimuth(delta); + % Ensure -90 <= delta <= 90 + delta(delta<-90) = -delta(delta<-90) - 180; + delta(delta>90) = -delta(delta>90) + 180; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m new file mode 100644 index 0000000000000000000000000000000000000000..73d74f7f70139b0ebf4cdd2a7f03da5ea5c59f14 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m @@ -0,0 +1,389 @@ +function [toa_diff,toa,IACC,Obj] = SOFAcalculateITD(Obj,varargin) +% SOFAcalculateITD: Estimate ITD from a binaural signal +% Usage: [itd,toa,IACC,Obj] = SOFAcalculateITD(data,mode,threshlvl,lowpass,butterpoly,upper_cutfreq) +% +% Input parameters: +% +% data: SOFA object or IR matrix with dimensions: +% emitter x receiver x time +% +% fs: sampling rate, used only if data provided as matrix +% +% mode: (optional) Select one estimation methods +% (Threshold (default),Cen_e2,MaxIACCr, MaxIACCe, +% CenIACCr,CenIACCe, CenIACC2e, PhminXcor,IRGD) +% +% lowpass: (optional) Bandwidth considered. lp for lowpass (default), bb for broadband +% +% peak: (optional) Method to find the max, used in Threshold mode only. +% hp for max (default), fb for findpeak +% +% threshlvl: (optional) Set threshold level for Threshold mode in dB. +% Default is -10 dB. +% +% butterpoly: (optional) Select the order of the polynom +% applied in the butterworth filter. ( 2 =< i =< 10 ) +% Default is 10. +% +% upper_cutfreq: (optional) Set frequency of lowpass cutoff in Hz. +% Default is 3000 Hz. +% +% lower_cutfreq: (optional) Set frequency of highpass cutoff in Hz, +% only used in IRGD mode. Default is 1000 Hz. +% +% debug : output debug information about calculations. +% +% +% Output parameters: +% +% itd: interaural time difference in seconds +% toa: detected activation onsets for left and right channels +% IACC: interaural cross-correlation coefficient +% Available on when xcorr is used (modes: MaxIACCr, MaxIACCe, +% CenIACCr,CenIACCe, CenIACC2e) +% Obj: Input SOFA object with Obj.Data.Delay added +% +% +% Purpose: +% Estimates the ITD based on biaural impulse responses. +% Several different estimaton methods can be chosen. +% MaxIAACe is recommended. +% +% +% Examples: +% --------- +% +% Obj = SOFAload(fullfile(SOFAdbPath,'baumgartner2017','hrtf b_nh15.sofa')); +% toa_diff = SOFAcalculateITD(Obj,'MaxIACCe','lp','upper_cutfreq',3000) +% +% With these settings the estimator uses the MaxIAAce method and applies +% a lowpass with a cut off frequency of 3 kHz. +% +% The output array is structured as the SOFA Data.IR +% If you would like to select for example only data on the horizontal +% plane you could: +% +% plane_idx = find( Obj.SourcePosition(:,2) == 0 ); +% plane_angle = Obj.SourcePosition(plane_idx,1); +% +% Url: https://amtoolbox.org/amt-1.2.0/doc/common/itdestimator_code.php + +% #Author: AMToolbox, Laurin Steidle, Piotr Majdak, Clara Hollomey, and the AMT team +% #Author: Robert Baumgartner: data matrix option +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% #Author: Michael Mihocic: adaption for SOFA Toolbox 2.0 +% #Author: Michael Mihocic: updated to version 1.2.0 of function itdestimator in Auditory Modeling Toolbox (AMT) (01.08.2022) +% +% This file is part of the SOFA Toolbox 2.0, +% basing on the function itdestimator in Auditory Modeling Toolbox (AMT) version 1.2.0 +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + + + +% ---------------------- SOFAarghelper ------------------------------- +% default parameters (adapted from arg_itdestimator) +definput.keyvals.debug = 0; +definput.flags.mode = {'Threshold','Cen_e2','MaxIACCr', 'MaxIACCe', 'CenIACCr', 'CenIACCe', 'CenIACC2e', 'PhminXcor','IRGD'}; +definput.flags.lp = {'lp','bb'}; +definput.flags.peak = {'hp','fp'}; +definput.flags.toaguess = {'noguess','guesstoa'}; +definput.keyvals.threshlvl = -10; +definput.keyvals.butterpoly = 10; +definput.keyvals.upper_cutfreq = 3000; +definput.keyvals.lower_cutfreq = 1000; +definput.keyvals.avgtoa = 45; +definput.keyvals.fs = []; +definput.keyvals.thr = 20; % dB +definput.keyvals.upsample = 16; % dB +definput.flags.units = {'time', 'samples'}; + +[flags,kv]=SOFAarghelper({},definput,varargin); + +% ---------------------- renaming input parameter --------------------- + +if isstruct(Obj) + pos = Obj.API.M; + ear = Obj.API.R; + Ns = Obj.API.N; + IR = Obj.Data.IR; + fs = Obj.Data.SamplingRate; +else + pos = size(Obj,1); + ear = size(Obj,2); + Ns = size(Obj,3); + IR = Obj; + if isempty(kv.fs) + error('RB: No sampling rate (fs) provided.') + end + fs = kv.fs; +end + +% ---------------------- initialising variables ----------------------- + +toa = zeros(pos,ear); +toa_diff = zeros(pos,1); +IACC = zeros(pos,1); +% delay = zeros(length(Obj.SourcePosition), 2); + +if kv.debug == 1; disp('SOFAcalculateITD:'); end + +% ---------------------- Applying low-pass ---------------------------- + +if flags.do_lp + if kv.debug == 1 + disp(' Applying Butterworth low pass ') + disp(strcat(' Polynomial order of Butterworth filter: ',num2str(kv.butterpoly))) + disp(strcat(' Cut-off frequency is: ',num2str(kv.upper_cutfreq),' Hz')) + end + % if isoctave; pkg load signal; end + if exist('OCTAVE_VERSION','builtin') ~= 0; pkg load signal; end + cut_off_freq_norm = kv.upper_cutfreq/(fs/2); + + [lp_a,lp_b] = butter(kv.butterpoly,cut_off_freq_norm); + f_ir = zeros(pos,ear,Ns); + for ii=1:pos + for jj=1:ear + sir = squeeze( IR(ii,jj,:) ); + f_sir = filter(lp_a,lp_b,sir); + f_ir(ii,jj,:) = f_sir; + end + end + +else + if kv.debug == 1; disp(' No low pass filter is applied'); end + f_ir = IR; +end + +% ---------------------- estimating itd ------------------------------- +% --------------------------------------------------------------------- + +% ---------------------- Threshold ------------------------------------ +switch(flags.mode) + case 'Threshold' + if kv.debug == 1 + disp(' Threshold mode') + disp(strcat(' Threshold level is: ',num2str(kv.threshlvl),'dB')) + end + + if flags.do_fp + for ii=1:pos + for jj=1:ear + indB = 0.5*mag2db(squeeze(f_ir(ii,jj,:)).^2); + [~,B] = findpeaks(indB); + th_value = indB(B(1)) + kv.threshlvl; + toa(ii,jj) = find(indB>th_value,1); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + else + for ii=1:pos + for jj=1:ear + indB = 0.5*mag2db(squeeze(f_ir(ii,jj,:)).^2); + th_value = max(indB) + kv.threshlvl; + idx=find(indB>th_value,1); + if isempty(idx), idx=NaN; end + toa(ii,jj) = idx; + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + end + + +% ---------------------- Cross-Correlation ---------------------------- + case 'Cen_e2' + if kv.debug == 1; disp(' Cen-e2 mode'); end + for ii=1:pos + for jj = 1:ear + e_sir_sq = abs(hilbert(squeeze(f_ir(ii,jj,:))).^2); + toa(ii,jj) = centroid(transpose(1:Ns),e_sir_sq); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + + case 'MaxIACCr' + if kv.debug == 1; disp(' MaxIACCr mode'); end + for ii=1:pos + cc = xcorr(squeeze(f_ir(ii,1,:)),squeeze(f_ir(ii,2,:))); + [IACC(ii),idx_lag] = max(abs(cc)); + toa_diff(ii) = idx_lag - Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + case 'MaxIACCe' + if kv.debug == 1; disp(' MaxIACCe mode'); end + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2); + [IACC(ii),idx_lag] = max(abs(cc)); + toa_diff(ii) = idx_lag - Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACCr' + if kv.debug == 1; disp(' CenIACCr mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + cc = xcorr(squeeze(f_ir(ii,1,:)),squeeze(f_ir(ii,2,:))); + pos_cc = abs(cc); + IACC(ii) = max(pos_cc); + toa_diff(ii) = centroid(x,pos_cc)-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACCe' + if kv.debug == 1; disp(' CenIACCe mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2); + IACC(ii) = max(abs(cc)); + toa_diff(ii) = centroid(x,abs(cc))-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACC2e' + if kv.debug == 1; disp(' CenIACC2e mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2).^2; + IACC(ii) = max(abs(cc)); + toa_diff(ii) = centroid(x,abs(cc))-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'PhminXcor' + if kv.debug == 1; disp(' PhminXcor mode'); end + ir_min=ARI_MinimalPhase(Obj); + for ii=1:pos + for jj=1:ear + cc = xcorr(squeeze(IR(ii,jj,:)),squeeze(ir_min(ii,jj,:))); + [~,toa(ii,jj)] = max(abs(cc)); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + +% ---------------------- Groupdelay ----------------------------------- + case 'IRGD' + if kv.debug == 1; disp(' IRGD mode'); end + for ii = 1:pos + for jj = 1:ear + f_sir = squeeze( f_ir(ii,jj,:) ); + [gd,w] = grpdelay(transpose(double(f_sir)),1,Ns,fs); + toa(ii,jj)=mean(gd(find(w>kv.lower_cutfreq): ... + find(w>kv.upper_cutfreq))); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end +end +toa_diff = toa_diff/fs; +toa = toa/fs; + +% Calculate Delay, add to Obj +for k = 1:size(IR, 1) + % Get onset + OnSetL = IR_start(IR(k,1,:), kv.thr); % L + OnSetR = IR_start(IR(k,2,:), kv.thr); % R + % Onset difference + delay(k,:) = [OnSetL, OnSetR]; +end + +Obj = SOFAaddVariable(Obj,'Data.Delay','MR',delay); + + + +% ------------------------------------------------------------------------- +% ---------------------- Functions ---------------------------------------- +% ------------------------------------------------------------------------- + + +% ---------------------- Centroid ----------------------------------------- +function idx_cent = centroid(x,y) +idx_cent = sum(x.*y)/sum(y); + +% ---------------------- guess toa ---------------------------------------- +function toa = guesstoa(toa_diff,toa, avgtoa) +toa(:,1) = toa(:,1) + avgtoa + toa_diff/2; +toa(:,2) = toa(:,2) + avgtoa - toa_diff/2; + +% ---------------------- Create minimal phase ----------------------------- +% as used in ziegelwanger2014 +function hMmin=ARI_MinimalPhase(Obj) +hM=Obj.Data.IR; +hMmin=hM; + +for jj=1:Obj.API.R + for ii=1:Obj.API.M + h=squeeze(hM(ii,jj,:)); + + amp1=abs(fft(h)); + amp2=amp1; + + an2u=-imag(hilbert(log(amp1))); + an2u=an2u(1:floor(length(h)/2)+1); + + an3u=[an2u; -flipud(an2u(2:end+mod(length(h),2)-1))]; + an3=an3u-round(an3u/2/pi)*2*pi; + + amp2=amp2(1:floor(length(h)/2)+1); + amp3=[amp2; flipud(amp2(2:end+mod(length(h),2)-1))]; + + h2=real(ifft(amp3.*exp(1i*an3))); + hMmin(ii,jj,:)=h2(1:Obj.API.N); + end +end + +% -------------------------- sampleStart ---------------------------------- +function sampleStart = IR_start(IR,threshold) +% 20210207 - Davi Carvalho, adapted from ita_start_IR.m from https://git.rwth-aachen.de/ita/toolbox/-/blob/master/kernel/DSP/ita_start_IR.m +threshold = -abs(threshold); +IR_square = IR.^2; +% Max value on IR +[pk_val, idx_max] = max(IR_square(:)); +abs_dat = 10.*log10(IR_square(1:idx_max)) - 10.*log10(pk_val); + +lastBelowThreshold = find(abs_dat < threshold,1,'last'); +if ~isempty(lastBelowThreshold) + sampleStart = lastBelowThreshold; +else + sampleStart = 1; +end +% Check if oscillations exist before the last value below threshold +% If so, these are part of the RIR and need to be considered. +idx6dBaboveThreshold = find(abs_dat(1:sampleStart) > threshold + 6); +if ~isempty(idx6dBaboveThreshold) + tmp = find(abs_dat(1:idx6dBaboveThreshold(1)) < threshold, 1 ,'last'); + if isempty(tmp) % without this if, the function would generate an error, if the oscillation persists until the first sample + sampleStart = 1; + else + sampleStart = tmp; + end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m new file mode 100644 index 0000000000000000000000000000000000000000..6fee405fec7c7dafdcdbbd9a65b4367f3fed38de --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m @@ -0,0 +1,111 @@ +function Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax) +% Low frequency extention +% +% function Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax) +% +% Description: +% This function extrapolates low frequency content of +% SOFA SimpleFreeFieldHRIR objects by considering a +% linear behavior to the low frequency content + +% Usage: Obj = SOFAcalculateLFE(Obj, fmin, fmax) +% +% Input parameters: +% Obj: SOFA object with SimpleFreeFieldHRIR convention. +% fmin: Minimal frequency to be calculated (default: 15Hz) +% fmax: Reference frequency value to be extended until fmin +% (default: 500Hz) +% +% Output arguments: +% Obj: SOFA object with SimpleFreeFieldHRIR convention. + + +% #Author: Davi R. Carvalho, UFSM - Acoustical Engineering (07.04.2021) +% #Author: Michael Mihocic: adapted for SOFA 2.0 release; header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcalculateLFE +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% parse inputs +if nargin < 3 + fmax = 500; % max linear frequency +end +if nargin < 2 + fmin = 15; % minimum freq +end + +%% Preprocess +fs = Obj.Data.SamplingRate; +IR = shiftdim(Obj.Data.IR, 2); +N = size(IR, 1); +freq_vec = (0:N/2-1)*fs/N; + +% Check if defined fmax data exists in raw hrir +if length(find(fmax > freq_vec)) == 1 + fmax = freq_vec(3); +end + + +% Minimum length necessary to contain fmin +N_ext = ceil(fs/fmin); +if N_ext <= N + N_ext = N; + freq_vec_ext = freq_vec; +else + freq_vec_ext = (0:N_ext/2-1)*fs/N_ext; +end +f500Hz = dsearchn(freq_vec_ext.', fmax); % idx at defined linear part of HRTFs + +[~, ~, ~, Obj] = SOFAcalculateITD(Obj, 'samples', 'debug', 1); +% [~, ObjD] = SOFAcalculateITDdavi(Obj, 'samples'); + +%% extrap low frequency +ir_interp = zeros(size(IR, 2), size(IR, 3), N_ext); +for k = 1:size(IR, 2) + for l = 1:size(IR, 3) + time = [IR(:,k,l); zeros(ceil(N_ext - N), 1)]; + mag = mag2db(abs(fft(time))); + mag_interp = mag; + + % interp + x = [1, f500Hz]; + xq = [1:f500Hz]; + y_mag = [mag(f500Hz); mag(f500Hz)]; + if exist('OCTAVE_VERSION','builtin') + mag_interp(1:f500Hz) = interp1(x, y_mag, xq); + else + mag_interp(1:f500Hz) = interp1(x, y_mag, xq, 'makima'); + end + + mag_interp = 10.^(mag_interp./20); + H = mag_interp(1:round(N_ext/2)); + + % back to time domain + ir_interp(k,l,:) = circshift(real(ifft(get_min_phase(abs(H)))), Obj.Data.Delay(k,l)); + end +end + + +%% OUTPUT +Obj_lfe = Obj; +% ir_interp = ir_interp./max(abs(ir_interp(:))) .* max(abs(IR(:))); +Obj_lfe.Data.IR = ir_interp; +end + + +function Hmin = get_min_phase(H, varargin) +% Calculate minimum-phase spectrum from magnitude via the Hilbert Transform +%% Preprocess +H = [H; flip(H)]; % back to double sided spectrum + +%% Get minimum_phase +phi_min = imag(hilbert(-(log(abs(H)+eps)))); % eps makes avoids log(0) = -inf +% Filtro inverso complexo (cria fase) +Hmin = abs(H).*exp(1i*(phi_min)); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m new file mode 100644 index 0000000000000000000000000000000000000000..cbf03103a4ae032e8078a9916fddb18a94f863a8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m @@ -0,0 +1,30 @@ +function newfn=SOFAcheckFilename(fn) +%SOFACHECKFILENAME +% newFN = SOFAcheckFilename(FN) checks the filename FN replaces certain characters + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcheckFilename +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% filename = string? +if ~ischar(fn) + error('Filename must be a string.'); +end +if strcmp(fn(1:7),'http://') + newfn=fn; % remote file +else + fn=strrep(fn,'/',filesep); + fn=strrep(fn,'\',filesep); + if length(fn)>4 + if strcmpi(fn(1:4),['db:' filesep]), fn=[SOFAdbPath fn(5:end)]; end + end + newfn=fn; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..c055c62533f41e7a6950b9d4de2b2d4cddf64f08 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m @@ -0,0 +1,93 @@ +function [Obj, log] = SOFAcompact(Obj) +%SOFAcompact +% Obj = SOFAcompact(Obj) +% compacts the unique value to singleton dimensions +% of variables where possible. +% Current limitation: Variables with 3 dimensions will be only compacted +% when the third dimension is the compressible one. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcompact +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence") +% You may not use this work except in compliance with the Licence. +% You may obtain a copy of the Licence at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the Licence for the specific language governing permissions and limitations under the Licence. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); +dims=SOFAdefinitions('dimensions'); + +%% compact w/o data +X=rmfield(Obj,{'Data','API'}); +Xf=fieldnames(X); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % get all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.(Xf{ii}),'rows'); else n=unique(Obj.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.(Xf{ii})=n; else Obj.(Xf{ii})=n'; end; % compressed! + case 3 + d=cell2mat(strfind(dims,'I')); + switch d + case 3 + y=unique(reshape(Obj.(Xf{ii}),[],size(Obj.(Xf{ii}),d))','rows'); + if size(y,1)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=reshape(y',size(Obj.(Xf{ii}),1),size(Obj.(Xf{ii}),2)); + otherwise + warning('SOFA:compact',[Xf{ii} ' not compressed (currently limited)']); + end + end +end + +%% Compact the data +Xf=fieldnames(Obj.Data); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.Data.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.Data.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.Data.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.Data.(Xf{ii}),'rows'); else n=unique(Obj.Data.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.Data.(Xf{ii})=n; else Obj.Data.(Xf{ii})=n'; end; % compressed! + case 3 + % missing + warning('SOFA:compact',['Data.' Xf{ii} ' not compressed (functionality limited)']); + end +end + +%% clean up +Obj=SOFAupdateDimensions(Obj); +if length(log)>1, log=log(2:end); else log={}; end; + +function vec=getdim(Obj,str) +vec=NaN(1,length(str)); +for ii=1:length(str) + vec(ii)=Obj.(upper(str(ii))); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m new file mode 100644 index 0000000000000000000000000000000000000000..f703e3f1318172591967cb13856444be985abe96 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m @@ -0,0 +1,58 @@ +function [tf,reason,where] = SOFAcompare(Obj1, Obj2, varargin) +%SOFAcompare +% TF = SOFAcompare(A, B) compares A and B and +% returns logical 1 (true) if they are identical. +% +% [TF,REASON,WHERE] = SOFAcompare(A, B) provides the REASON +% and shows WHERE the difference arose. +% +% ... = SOFAcompare(A, B, 'ignoreDate') ignores the global attributes +% DateCreated and DateModified. +% +% +% Limited functionality!!! Only attributes are compared now. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAcompare +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.flags.type={'all','ignoreDate'}; +[flags,~]=SOFAarghelper({},definput,varargin); + + +tf=1; +reason=''; +where=''; + +% % check if the size is equal +% o1=whos('Obj1'); +% o2=whos('Obj2'); +% if o1.bytes ~= o2.bytes, tf=0; reason='Different size'; return; end + + % get the field names +Xf=fieldnames(Obj1); + + % ignore DateCreated and DateModified? +if flags.do_ignoreDate + Xf=fieldnames(rmfield(Obj1,{'GLOBAL_DateCreated','GLOBAL_DateModified'})); +end + + % check if we have the same fields in Obj2 as in Obj1 +for ii=1:length(Xf) + if ~isfield(Obj2,Xf{ii}), tf=0; reason='Field missing in B'; where=Xf{ii}; return; end +end + + % check if we have the same content of attributes in Obj2 as in Obj1 +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), continue; end + if ~strcmp(Obj1.(Xf{ii}),Obj2.(Xf{ii})), tf=0; reason='Field not equal'; where=Xf{ii}; return; end +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..d1919ecf97105fd41955d27d2bd6238551f4e422 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m @@ -0,0 +1,209 @@ +function [dispOutput] = SOFAcompileConventions(conventions) +%SOFAcompileConventions +% +% [dispOutput] = SOFAcompileConventions(sofaconventions) compiles the specified +% SOFA conventions. For every convention, a CSV file must exist that +% will be compiled to a .mat file and used later by SOFAgetConventions(). +% +% The CSV file must be in the directory conventions and can contain +% files for multiple versions of the same conventions. For each version, +% SOFAcompileConventions generates 3 files, one for each flag (r, m, and all) +% +% Before compiling, SOFAcompileConventions checks if the modification +% date of the .mat files is older than that of the .csv file. Compiling +% is not performed if all .mat files are newer than the .csv file. This +% behaviour is required for operation in a read-only directory. +% +% SOFAcompileConventions ignores all files beginning with '_' (underscore). +% +% Output variable dispOutput contains a string with all compiled +% conventions information. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (20.10.2021) +% #Author: Michael Mihocic: display information changed to output variable (11.11.2021) +% +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +baseFolder = fileparts(which('SOFAstart')); +dispOutput=''; + +if nargin<1 + conventionFiles = dir(fullfile(baseFolder,'conventions','*.csv')); + conventions={}; + for file = conventionFiles' + [~,name,~] = fileparts(file.name); + if name(1)=='_', continue; end + % Check if mat files exist for every convention flag (r,m,a) + flagsCounter = 0; + for flag = 'rma' + flagFile = dir(fullfile(baseFolder,'conventions', ... + strcat(name,'_',flag,'_*.mat'))); + if ~isempty(flagFile) && flagFile(1).datenum>file.datenum + flagsCounter = flagsCounter+1; + end + end + % If not all three files are up to request conventions compilation + if flagsCounter~=3 + conventions{end+1} = name; + end + end +elseif ~iscell(conventions) + conventions={conventions}; +end + + +%% ----- Convert convention csv files into mat files ----- +for convention = conventions + % Read convention description from csv file + fid = fopen(fullfile(baseFolder,'conventions', ... + strcat(convention{:},'.csv'))); + if exist('OCTAVE_VERSION','builtin') + % We're in Octave where textscan works differently since ver. 4.2 + C_lines = textscan(fid,'%s','Delimiter','\n','Headerlines',1); + C_line = C_lines{1}{1}; + C_elems = cell(length(C_lines{1}),1); + C_maxcols = 2; + for line_nr = 1:length(C_lines{1}) + C_line = C_lines{1}{line_nr}; + C_elems{line_nr} = strsplit(C_line, '\t', 'collapsedelimiters', false); + C_maxcols = max(C_maxcols, length(C_elems{line_nr})); + end + % C = cell(1,length(C_elems{1})); + C = cell(1,C_maxcols); + for col_nr = 1:C_maxcols + % for col_nr = 1:length(C_elems{1}) + C{col_nr} = cell(length(C_lines{1}),1); + end + for line_nr = 1:length(C_lines{1}) + for col_nr = 1:length(C_elems{line_nr}) + % for col_nr = 1:length(C_elems{1}) + C{col_nr}{line_nr} = C_elems{line_nr}{col_nr}; + end + end + else + x=char(fread(fid)); + xr=strrep(x',char([9 13 10]),char([9 32 32 13 10])); + C = textscan(xr,'%s%s%s%s%s%s','Delimiter','\t','Headerlines',1,'WhiteSpace',''); + end + fclose(fid); + + % Convert to mat files for r,m,a cases + for flag = 'rma' + % Convert to SOFA object + Obj = compileConvention(C,flag); + % Write to mat file +% if strcmp(Obj.GLOBAL_SOFAConventions,convention{:}) + if strcmp(flag,'r') % && dispOutput==1 % Display message only the very first time +% disp(['Compiling ',convention{:},'.csv: ', ... +% Obj.GLOBAL_SOFAConventions, ' ', ... +% Obj.GLOBAL_SOFAConventionsVersion]); + if ~strcmp(dispOutput,''); dispOutput = [dispOutput 10]; end + dispOutput = [dispOutput 'Compiling ',convention{:},'.csv: ', Obj.GLOBAL_SOFAConventions, ' ', Obj.GLOBAL_SOFAConventionsVersion]; + end + save(fullfile(baseFolder,'conventions', ... + strcat(Obj.GLOBAL_SOFAConventions,'_',flag,'_', Obj.GLOBAL_SOFAConventionsVersion,'.mat')), ... + 'Obj','-v7'); +% else +% warning([convention{:} '.csv: file name not convention name (' Obj.GLOBAL_SOFAConventions]); +% end + end +end +end % of main function + + +%% ----- Subroutines ----------------------------------------------------- +function Obj = compileConvention(convention,flag) + % Compile convention mat structure for the specified flag + % + % The csv files provide the following columns (corresponding cell numbers in + % brackets) + % Name {1}, Default {2}, Flags {3}, Dimensions {4}, Type {5}, Comment {6} + convName = convention{1}; + convDefault = convention{2}; + convFlags = convention{3}; + convDimensions = convention{4}; + convType = convention{5}; + convComment = convention{6}; + + % Create object structure + for ii=1:length(convName) + % Append 'a' to Flags entry as it only contains 'm' or 'r' in the csv file + convFlags{ii} = strcat(convFlags{ii},'a'); + if ~isempty(regexp(convFlags{ii},flag, 'once')) + var = regexprep(convName{ii},':','_'); + switch lower(convType{ii}) + case 'double' + % Convert default to double + convDefault{ii} = str2num(convDefault{ii}); + case 'string' + eval(['convDefault{ii}=' convDefault{ii} ';']); + end + if isempty(strfind(var,'Data.')) + Obj.(var) = convDefault{ii}; + if isempty(strfind(var,'_')) % && ~sum(strcmp(var,dims)) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quotations and insert line breaks + Obj.API.Dimensions.(var)=eval(['{''' y '''}']); + end + else + Obj.Data.(var(6:end)) = convDefault{ii}; + if isempty(strfind(var(6:end),'_')) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quatations and insert line breaks + Obj.API.Dimensions.Data.(var(6:end))=eval(['{''' y '''}']); + end + end + end + end + + + % ----- Overwrite some special fields ----- + if isfield(Obj,'GLOBAL_APIVersion') + Obj.GLOBAL_APIVersion = SOFAgetVersion; + end + if isfield(Obj,'GLOBAL_APIName') + Obj.GLOBAL_APIName = 'ARI Matlab/Octave API'; + end + + % ----- Create dimension size variables - if not read-only ----- + if strcmp(flag,'r') + return; + else + % Fix dimension sizes (why we have to fix them?) + Obj.API.I = 1; + Obj.API.C = 3; + % Variable-dependent dimension sizes + dims = 'renm'; + % Check all metadata variables + fields =fieldnames(rmfield(Obj.API.Dimensions,'Data')); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(fields{jj}),dim(1)); + break; + end + end + end + % Check all data variables + fields = fieldnames(Obj.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.Data.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fields{jj}),dim(1)); + break; + end + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..577719ebb84f7a8e5f299e8c3de1404d1a07562d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m @@ -0,0 +1,461 @@ +function Obj=SOFAconvertConventions(Obj,varargin) +% Obj = SOFAconvertConventions(Obj) converts a SOFA object to SimpleFreeFieldHRIR +% +% Supported conventions: +% SimpleFreeFieldSOS +% SimpleFreeFieldTF +% SimpleFreeFieldHRTF +% FreeFieldHRTF +% some special cases of GeneralTF, GeneralTF-E. +% +% When using optional input values, they are transferred to and must be supported by SOFAarghelper function: +% Obj=SOFAconvertConventions(Obj,varargin) +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% get convention to be converted +if ~isempty(varargin) + definput.flags.convention=SOFAgetConventions(); + definput.flags.convention=strrep(definput.flags.convention,'-','_'); + + if contains(varargin,'-') + varargin=strrep(varargin,'-','_'); + end + [flags,~]=SOFAarghelper({},definput,varargin); + + newConvention = flags.convention; + if contains(newConvention,'_') + newConvention=strrep(newConvention,'_','-'); + end + % check if given convention is available + if isempty( SOFAgetConventions(newConvention)) + error([newConvention, ' not a valid convention.']) + end +else + newConvention = 'SimpleFreeFieldHRIR'; +end +oldConvention = Obj.GLOBAL_SOFAConventions; +%% no conversion needed if convention is the same +if(strcmp(oldConvention,newConvention)) +% warning(['No conversion done, as Obj already conforms to ', newConvention,'.']) + return +end + +%% convert Object +newObj = SOFAgetConventions(newConvention); +oldObj = SOFAgetConventions(oldConvention); + +Obj.GLOBAL_SOFAConventions=newObj.GLOBAL_SOFAConventions; +Obj.GLOBAL_SOFAConventionsVersion=newObj.GLOBAL_SOFAConventionsVersion; +Obj.GLOBAL_Conventions = newObj.GLOBAL_Conventions; +% convert Data +try + switch Obj.GLOBAL_DataType + case 'SOS' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + Obj.Data.IR(ii,jj,:)=sosfilt(reshape(squeeze(Obj.Data.SOS(ii,jj,:)),6,[])',impulse); + end + end + Obj.Data=rmfield(Obj.Data,'SOS'); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Data.SOS = Obj.Data.SOS; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + IR=sosfilt(reshape(squeeze(Data.SOS(ii,jj,:)),6,[])',impulse); + TF=fft(IR,Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Data.SOS = Obj.Data.SOS; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + IR=sosfilt(reshape(squeeze(Data.SOS(ii,jj,:)),6,[])',impulse); + TF=fft(IR,Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + Obj=SOFAupdateDimensions(Obj); + + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + + case 'TF' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + if sum(diff(diff(Obj.N))) + fs=max(Obj.N)*2; % irregular grid, find the smallest frequency difference + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + Nidx=Obj.N*N/fs+1; + Nsize=floor(N/2+1); + else + N=2*(length(Obj.N)-1); % regular grid (from an DFT probably), works for odd length only + fs=max(Obj.N)*2; + Nidx=1:length(Obj.N); + Nsize=length(Obj.N); + end + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=fs; + Obj.Data.SamplingRate_Units='hertz'; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(Nsize,1); + s(Nidx)=squeeze(Obj.Data.Real(ii,jj,:))+1i*squeeze(Obj.Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); + end + Obj.Data.Delay=zeros(1,Obj.API.R); + Obj.SourcePosition_Type=newObj.SourcePosition_Type; + Obj.SourcePosition_Units=newObj.SourcePosition_Units; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag'}); + if isfield(Obj.API.Dimensions,'Data') + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + end + elseif strcmp(newObj.GLOBAL_DataType,'TF') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType = newObj.GLOBAL_DataType; + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + + + case 'TF-E' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=max(Obj.N)*2; + Obj.Data.SamplingRate_Units='hertz'; + % convert sperical harmonics + if strcmpi(Obj.EmitterPosition_Type,'spherical harmonics') + [X,Y,Z]=sphere(60); + [azi_rad,ele_rad,radius]=cart2sph(X,Y,Z); + azi=azi_rad/pi*180; + ele=ele_rad/pi*180; + [azi,ele]=nav2sph(azi,ele); + radius=1.2*radius; + azi=azi(:); + ele=ele(:); + radius=radius(:); + + S = sph2SH([azi ele], sqrt(Obj.API.E)-1); + Obj.API.M=size(S,1); + Obj.SourcePosition=[azi ele radius]; + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degrees,degrees,metre'; + + Data.Real = zeros(Obj.API.M,2,Obj.API.N); + Data.Imag = zeros(Obj.API.M,2,Obj.API.N); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Data.Real(:,ii,jj)=S*squeeze(Obj.Data.Real(1,ii,jj,:)); + Data.Imag(:,ii,jj)=S*squeeze(Obj.Data.Imag(1,ii,jj,:)); + end + end + else +% Obj.EmitterPosition=Obj.SourcePosition; +% Obj.EmitterPosition_Type=Obj.SourcePosition_Type; +% Obj.EmitterPosition_Units=Obj.SourcePosition_Units; +% Data.Real = shiftdim(squeeze(Obj.Data.Real(1,:,:,:)),2); +% Data.Imag = shiftdim(squeeze(Obj.Data.Imag(1,:,:,:)),2); +% Obj.API.M=Obj.API.E; + error(['Converting ' Obj.GLOBAL_SOFAConventions ' to ' newObj.GLOBAL_SOFAConventions ' not supported yet']); + end + + if sum(diff(diff(Obj.N))) + fs=max(Obj.N)*2; % irregular grid, find the smallest frequency difference + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + Nidx=Obj.N*N/fs+1; + Nsize=floor(N/2+1); + else + N=2*(length(Obj.N)-1); % regular grid (from an DFT probably), works for odd length only + fs=max(Obj.N)*2; + Nidx=1:length(Obj.N); + Nsize=length(Obj.N); + end + + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(Nsize,1); + s(Nidx)=squeeze(Data.Real(ii,jj,:))+1i*squeeze(Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); + end + Obj.Data.Delay=zeros(Obj.API.M,Obj.API.R,1); + Obj.Data.SamplingRate=fs; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag'}); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + % convert sperical harmonics + if strcmpi(Obj.EmitterPosition_Type,'harmonics') + [X,Y,Z]=sphere(60); + [azi_rad,ele_rad,radius]=cart2sph(X,Y,Z); + azi=azi_rad/pi*180; + ele=ele_rad/pi*180; + [azi,ele]=nav2sph(azi,ele); + radius=1.2*radius; + azi=azi(:); + ele=ele(:); + radius=radius(:); + + S = sph2SH([azi ele], sqrt(Obj.API.E)-1); + Obj.API.M=size(S,1); + Obj.SourcePosition=radius; + Obj.SourcePosition_Type='spherical harmonics'; + Obj.SourcePosition_Units='metre'; + + oldObj.Data.Real = Obj.Data.Real; + oldObj.Data.Imag = Obj.Data.Imag; + Obj.Data.Real = zeros(Obj.API.M,2,Obj.API.N); + Obj.Data.Imag = zeros(Obj.API.M,2,Obj.API.N); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(:,ii,jj)=S*squeeze(oldObj.Data.Real(1,ii,jj,:)); + Obj.Data.Imag(:,ii,jj)=S*squeeze(oldObj.Data.Imag(1,ii,jj,:)); + end + end + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; + else + error('Conventions not supported'); + end + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + % no data conversion needed + end + + case 'FIR' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + IR=Obj.Data.IR; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + TF=fft(IR(ii,jj,:),Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + IR=Obj.Data.IR; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + TF=fft(IR(ii,jj,:),Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj=SOFAupdateDimensions(Obj); + + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + otherwise + error(['Turning ',oldConvention,' into ',... + newObj.GLOBAL_SOFAConventions,' not supported.']); + end +catch ME + rethrow(ME); + error(['Turning ',oldConvention,' into ',... + newObj.GLOBAL_SOFAConventions,' not supported.']); +end +Obj.SourcePosition=SOFAconvertCoordinates(Obj.SourcePosition,Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); +Obj.SourcePosition_Type=newObj.SourcePosition_Type; +Obj.SourcePosition_Units=newObj.SourcePosition_Units; +if strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics') && ~strcmpi(newObj.EmitterPosition_Type,'Spherical Harmonics') + Obj.EmitterPosition=[0 0 0]; + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; +elseif ~strcmpi(newObj.EmitterPosition_Type,'Spherical Harmonics') + Obj.EmitterPosition=SOFAconvertCoordinates(Obj.EmitterPosition,Obj.EmitterPosition_Type,newObj.EmitterPosition_Type,Obj.EmitterPosition_Units,newObj.EmitterPosition_Units); + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; +end +Obj.ListenerPosition=SOFAconvertCoordinates(Obj.ListenerPosition,Obj.ListenerPosition_Type,newObj.ListenerPosition_Type,Obj.ListenerPosition_Units,newObj.ListenerPosition_Units); +Obj.ListenerPosition_Type=newObj.ListenerPosition_Type; +Obj.ListenerPosition_Units=newObj.ListenerPosition_Units; +Obj.ReceiverPosition=SOFAconvertCoordinates(Obj.ReceiverPosition,Obj.ReceiverPosition_Type,newObj.ReceiverPosition_Type,Obj.ReceiverPosition_Units,newObj.ReceiverPosition_Units); +Obj.ReceiverPosition_Type=newObj.ReceiverPosition_Type; +Obj.ReceiverPosition_Units=newObj.ReceiverPosition_Units; +Obj=SOFAupdateDimensions(Obj); + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m new file mode 100644 index 0000000000000000000000000000000000000000..50b4f392c3e5971f5efc632389a978dee6cd7bc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m @@ -0,0 +1,66 @@ + function output = SOFAconvertCoordinates(input,input_type,output_type,~,~) +%SOFAconvertCoordinates +% output = SOFAconvertCoordinates(input,input_type,output_type), converts the specified coordinate variable to specified +% output_type and returns the results. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: type horizontal-polar removed (not defined in SOFA) (08.03.2021) +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAconvertCoordinates +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% check input +if strcmp(input_type,'cartesian')==0 && ... + strcmp(input_type,'spherical')==0 && ... + strcmp(input_type,'geodesic')==0 % && ... +% strcmp(input_type,'horizontal-polar')==0 + error('Specified "input_type" is not supported'); +end +if strcmp(output_type,'cartesian')==0 && ... + strcmp(output_type,'spherical')==0 && ... + strcmp(output_type,'geodesic')==0 % && ... +% strcmp(output_type,'horizontal-polar')==0 + error('Specified "output_type" is not supported'); +end + +output=input; +%% convert coordinates if necessary +if strcmp(output_type,input_type)==0 + temp=input; + switch input_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [temp(:,1),temp(:,2),temp(:,3)]=sph2cart(deg2rad(input(:,1)),deg2rad(input(:,2)),input(:,3)); +% case 'horizontal-polar' +% [temp(:,1),temp(:,3),temp(:,2)]=sph2cart(deg2rad(input(:,2)),deg2rad(input(:,1)),input(:,3)); +% temp(:,2)=-temp(:,2); + end + + output=temp; + switch output_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [output(:,1),output(:,2),output(:,3)]=cart2sph(temp(:,1),temp(:,2),temp(:,3)); + output(:,1:2)=rad2deg(output(:,1:2)); +% case 'horizontal-polar' +% % [output(:,2),output(:,1),output(:,3)]=cart2sph(temp(:,1),temp(:,3),-temp(:,2)); +% % output(:,1:2)=rad2deg(output(:,1:2)); +% % output(:,1)=-output(:,1); +% % output(:,2)= mod(output(:,2)+90,360)-90; +% [output(:,1),output(:,2),output(:,3)]=cart2sph(temp(:,1),temp(:,3),-temp(:,2)); +% [output(:,1),output(:,2)]=sph2hor(output(:,1),output(:,2)); + end +end + + + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m new file mode 100644 index 0000000000000000000000000000000000000000..127d1519f9a4d98205ff8ec4172f0ed0c40768ad --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m @@ -0,0 +1,35 @@ +function dbPath=SOFAdbPath(newPath) +% dbPath=SOFAdbPath(newPath) +% +% dbPath=SOFAdbPath returns the path to the directory containing +% HRTFs for demos and applications. The default path is: this_directory/../data/SOFA +% +% [...]=SOFAdbPath(newPath) sets the path to the directory for further calls +% of SOFAdbPath. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAstart +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedPath; + +if exist('newPath','var') + if strcmp(newPath,'reset') + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'data','SOFA'); + else + CachedPath=newPath; + end +elseif isempty(CachedPath) + % default: 'this_directory/../data/SOFA' + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'data','SOFA'); +end +dbPath=CachedPath; + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m new file mode 100644 index 0000000000000000000000000000000000000000..ba17308dab105a995a29dc8d681cf70c7c667fd1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m @@ -0,0 +1,32 @@ +function dbURL=SOFAdbURL(dbURL) +% dbURL=SOFAdbURL +% +% dbURL=SOFAdbURL returns the internet URL to the directory containing +% HRTFs. The default URL is http://www.sofacoustics.org/data. +% +% dbURL=SOFAdbURL(newURL) sets the internet URL to the newURL for further calls +% of SOFAdbURL. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAdbURL +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedURL; + +if exist('dbURL','var') + if strcmp(dbURL,'reset') + CachedURL='http://www.sofacoustics.org/data'; + else + CachedURL=dbURL; + end +elseif isempty(CachedURL) + CachedURL='http://www.sofacoustics.org/data'; +end +dbURL=CachedURL; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m new file mode 100644 index 0000000000000000000000000000000000000000..d8cf1c7130e7ae73636cb77218e779ba99d328e6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m @@ -0,0 +1,83 @@ +function output = SOFAdefinitions(varargin) +% output = SOFAdefinitions(varargin) +% +% SOFAdefinitions returns a struct containing definitions like the time +% format used in the API. +% +% SOFAdefinitions('dateFormat') returns the date format +% +% SOFAdefinitions('APIName') returns the APIName +% +% SOFAdefinitions('dimensions') returns the dimensions used in the API +% +% SOFAdefinitions('EOL') returns the end-of-line separator used in the API +% +% SOFAdefinitions('dateReference') returns the string with the reference +% for the date when stored as numeric (number of seconds elapsed) +% +% SOFAdefinitions('units') returns the units and their corresponding aliases +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAdefinitions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +definput.flags.type={'all','dateFormat','APIName','dimensions','EOL','dateReference','units'}; +[flags,kv]=SOFAarghelper({},definput,varargin); + +%% Return all definitions in a structure +if flags.do_all, + output.APIName = SOFAdefinitions('APIName'); + output.dateFormat = SOFAdefinitions('dateFormat'); + output.dimensions = SOFAdefinitions('dimensions'); + output.EOL = SOFAdefinitions('EOL'); + output.dateReference = SOFAdefinitions('dateReference'); + output.units=SOFAdefinitions('units'); +end + +%% name of the API +if flags.do_APIName, + output = 'ARI SOFA Toolbox for Matlab/Octave'; +end + +%% date string to use (see help datestr) +if flags.do_dateFormat, + output = 'yyyy-mm-dd HH:MM:SS'; +end + +%% EOL to use +if flags.do_EOL, + output = char(10); +end + +%% dimensions to use +if flags.do_dimensions, + output.M = 'M'; % Number of Measurements + output.R = 'R'; % Number of Receivers + output.N = 'N'; % Number of Samples or the way you represent your data + output.E = 'E'; % Number of Emitters + output.C = 'C'; % Coordinates + output.I = 'I'; % Singleton + output.S = 'S'; % size of the largest string +end + +%% reference for date when used as numeric (number of seconds elapsed) +if flags.do_dateReference, + output = '1970-01-01 00:00:00'; +end + +%% return units with defined aliases +if flags.do_units, + output.metre={'metres','meter','meters'}; + output.degree={'degrees'}; + output.second={'seconds'}; +end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m new file mode 100644 index 0000000000000000000000000000000000000000..e70a93b875909b89d2a09ba60ffd5b3c87dcaeec --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m @@ -0,0 +1,137 @@ +function [Obj, log] = SOFAexpand(Obj,VarName) +%SOFAexpand +% Obj = SOFAexpand(Obj) expands the singleton dimensions of all variables. +% Only variables will be expanded. Data and attributes won't. Note that Obj.API.Dimensions will be updated to the new dimensions. +% +% Obj = SOFAexpand(Obj,VarName) expands the singleton dimensions of the variable VarName. +% +% [Obj,log] = SOFAexpand(...) returns a log of expanded variables. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAexpand +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj,'nodata'); + +%% If VarName given, expand a single variable only +if ~exist('VarName','var'), + + %% Expand all variables + % create field names which should have dimensions + X=rmfield(Obj,{'Data','API'}); + if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end + Xf=fieldnames(X); + + % Update the dimensions structure w/o data + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.(Xf{ii})=varNew; + Obj.API.Dimensions.(Xf{ii})=dimNew; + log{end+1}=[Xf{ii} ' expanded to ' dimNew]; + end + end + + % Expand the dimensions of Data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.Data.(Xf{ii})=varNew; + Obj.API.Dimensions.Data.(Xf{ii})=dimNew; + log{end+1}=['Data.' Xf{ii} ' expanded to ' dimNew]; + end + end + + +else % Expand a single variable only + if isempty(strfind(VarName,'_')), % is an attribute --> not expandable + if strncmp(VarName,'Data.',length('Data.')) + % variable within the Data. structure + VarName=VarName(length('Data.')+1:end); + if isfield(OC.API.Dimensions.Data, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,VarName,dim); + if ~isempty(varNew), + Obj.Data.(VarName)=varNew; + Obj.API.Dimensions.Data.(VarName)=dimNew; + log{end+1}=['Data.' VarName ' expanded to ' dimNew]; + end + end + end + else + if isfield(OC.API.Dimensions, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,VarName,dim); + if ~isempty(varNew), + Obj.(VarName)=varNew; + Obj.API.Dimensions.(VarName)=dimNew; + log{end+1}=[VarName ' expanded to ' dimNew]; + end + end + end + end + end +end + +%% log variable +if length(log)>1, log=log(2:end); else log={}; end; + +%% expand a single variable +% Obj: the full SOFA object +% f: name of the variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expand(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.(f),ones([getdim(Obj,dN) 1])); + end + if ~exist('var','var'), var=[]; dN=[]; end; +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); + +%% expand a single Data variable +% Obj: the full SOFA object +% f: name of the Data variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expandData(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.Data.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.Data.(f),ones([getdim(Obj,dN) 1])); + end + if ~exist('var','var'), var=[]; dN=[]; end; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m new file mode 100644 index 0000000000000000000000000000000000000000..66a7a03b20af0db83d99642ba735336217235e15 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m @@ -0,0 +1,47 @@ +function [idx, azinew, elenew, rnew] = SOFAfind(Obj,azi,ele,r) +% SOFAfind +% [idx, azi, ele, r] = SOFAfind(Obj, azi, ele, r) finds the indecies to +% the HRTFs from OBJ according to the trajectory given in AZI, ELE, R. +% Input: +% Obj: SOFA object containing HRTFs +% azi, ele: direction (in degrees) for azimuth and elevation +% r: optional radius. If not provided, radius will be ignored. +% +% Output: +% idx: index of the filters (corresponds to AZI and ELE) +% azi, ele: azimuth and elevation of the actual position (degrees) +% r: actual radius +% + +% #Author: Piotr Majdak (2019) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - SOFAfind +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + +%% create a 2D-grid with nearest positions +if ~exist('r','var'), + r=1; + Obj.SourcePosition(:,3)=r; +end +pos=SOFAconvertCoordinates(Obj.SourcePosition,'spherical','cartesian'); +idx=zeros(length(azi),1); +for ii=1:length(azi) + [t(:,1),t(:,2),t(:,3)] = sph2cart(deg2rad(azi(ii)),deg2rad(ele(ii)),r); + dist = sum((pos-repmat(t,size(pos,1),1)).^2,2); + [~,idx(ii)]=min(dist); +end + +%% Output +% actually used angles +azinew = Obj.SourcePosition(idx,1); +elenew = Obj.SourcePosition(idx,2); +rnew = Obj.SourcePosition(idx,3); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..4eef2508553f6bd0c0ac892efc16b878d22b6f3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m @@ -0,0 +1,139 @@ +function Obj = SOFAgetConventions(sofaconventions,flags,version) +%SOFAgetConventions +% +% List = SOFAgetConventions() returns a list with supported conventions. +% +% Obj = SOFAgetConventions(sofaconvention) returns a SOFA object +% with all metadata and data for the corresponding sofaconvention. Obj +% will be empty if sofaconventions is not supported. +% +% Obj = SOFAgetConventions(sofaconvention, flags) returns only selected +% metadata for the corresponding sofaconvention with the following encoding: +% m: mandatory +% r: readonly +% a: all (default) +% +% Obj = SOFAgetConventions(sofaconvention, version) returns only the selected +% version of the convention. +% +% Obj = SOFAgetConventions(sofaconvention, flag, version) returns only the selected +% version and metadata. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAgetConventions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Cache +persistent AllObj; + +%% If flags not provided, return the conventions with all metadata +if ~exist('version','var') + if ~exist('flags','var') + flags='a'; % no flags, no version --> flags = a, version = any. + else + switch flags % no version, check if flags is flags or version + case {'a', 'm', 'r'} + % flags is flags --> do nothing + otherwise + version=flags; % flags is version --> copy to version + flags='a'; + end + end +end + + +%% If sofaconventions not provided, return the list with supported conventions +if ~exist('sofaconventions','var') + p=mfilename('fullpath'); + d=dir([p(1:length(p)-length(mfilename)) 'conventions' filesep '*_m_*.mat']); + Obj={}; + for ii=1:length(d) + dn=d(ii).name; + idx=strfind(dn,'_'); + Obj{ii,1}=dn(1:idx(1)-1); + end + Obj=unique(Obj); + AllObj=[]; + return; +end + +%% Load cached object + +if isfield(AllObj,flags) + if isfield(AllObj.(flags).Obj,'GLOBAL_SOFAConventions') + if strcmp(AllObj.(flags).Obj.GLOBAL_SOFAConventions,sofaconventions) + if ~exist('version','var') + Obj=AllObj.(flags).Obj; % return cached convention object + else + if strcmp(AllObj.(flags).Obj.GLOBAL_SOFAConventionsVersion,version) + Obj=AllObj.(flags).Obj; % return cached convention object + end + end + end + end +end + +if ~exist('Obj','var') + % cached object not loaded yet + p=mfilename('fullpath'); + if exist('version','var') + % load a specific version but do not store in the cache + if ~isempty(dir([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '_' flags '_' version '.mat'])) + load([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '_' flags '_' version '.mat']); + else + error(['Convention ' sofaconventions ' with the version ' version ' not found.']); + end + else + allver=dir(fullfile(p(1:length(p)-length(mfilename)), 'conventions' , [sofaconventions '_' flags '_*.mat'])); + if isempty(allver) + warning(['Convention ' sofaconventions ' not found.']'); + Obj=[]; + else + vermax='0.0'; + idxmax=0; + for ii=1:length(allver) + x=load([p(1:length(p)-length(mfilename)) 'conventions' filesep allver(ii).name]); + if compareversions(x.Obj.GLOBAL_SOFAConventionsVersion,vermax)>0 + vermax=x.Obj.GLOBAL_SOFAConventionsVersion; + idxmax=ii; + end + end + % store in cache + AllObj.(flags)=load([p(1:length(p)-length(mfilename)) 'conventions' filesep allver(idxmax).name]); + Obj=AllObj.(flags).Obj; % return the cached version + end + end +end + +%% Overwrite some special fields +if isfield(Obj,'GLOBAL_DateCreated'), Obj.GLOBAL_DateCreated=datestr(now,SOFAdefinitions('dateFormat')); end +if isfield(Obj,'GLOBAL_APIVersion'), Obj.GLOBAL_APIVersion=SOFAgetVersion; end +if isfield(Obj,'GLOBAL_APIName'), Obj.GLOBAL_APIName=SOFAdefinitions('APIName'); end + +end + +function res=compareversions(ver1, ver2) + + [~,maj1,min1]=fileparts(ver1); + [~,maj2,min2]=fileparts(ver2); + maj1=str2num(maj1); + min1=str2num(min1(2:end)); + maj2=str2num(maj2); + min2=str2num(min2(2:end)); + if maj1>maj2 + res=1; % ver1 > ver2 + elseif maj1==maj2 && min1>min2 + res=1; % ver1 > ver2 + elseif maj2==maj2 && min1==min2 + res=0; % ver1 == ver2 + else + res=-1; % ver < ver2 + end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m new file mode 100644 index 0000000000000000000000000000000000000000..df4b8d814ad546db955081fbc1b4a55bb085c2d5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m @@ -0,0 +1,29 @@ +function results = SOFAgetVersion(flag) +%SOFAGETVERSION +% version = SOFAgetVersion() returns the version of the SOFA Toolbox API +% +% version = SOFAgetVersion('API') does the same. +% +% version = SOFAgetVersion('SOFA') returns the version of the SOFA supported by this Toolbox API. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAgetVersion +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~exist('flag','var') + flag='API'; +end + +switch flag + case 'API' + results = '2.0'; + case 'SOFA' + results = '2.0'; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m new file mode 100644 index 0000000000000000000000000000000000000000..adc80e62a97661bbd6f14cea66311d770c0416bd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m @@ -0,0 +1,87 @@ +function SOFAinfo(Obj) +% SOFAinfo(Obj) gathers (mandatory) information about the SOFA object and +% display it. For SimpleFreeFieldHRIR some more details are displayed. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Global fields + +disp('### SOFAinfo: ###') +disp([Obj.GLOBAL_Conventions ' ' Obj.GLOBAL_Version]) +disp(['Conventions: ' Obj.GLOBAL_SOFAConventions ' ' Obj.GLOBAL_SOFAConventionsVersion]) +disp(['API: ' Obj.GLOBAL_APIName ' ' Obj.GLOBAL_APIVersion]) +disp(['Data Type: ' Obj.GLOBAL_DataType]) +disp(['Room Type: ' Obj.GLOBAL_RoomType]) +disp(['Date Created: ' Obj.GLOBAL_DateCreated]) +disp(['Date Modified: ' Obj.GLOBAL_DateModified]) +disp(['Author Contact: ' Obj.GLOBAL_AuthorContact]) +disp(['Organization: ' Obj.GLOBAL_Organization]) +disp(['License: ' Obj.GLOBAL_License]) +disp(['Title: ' Obj.GLOBAL_Title]) + + +%% Conventions dependant fields + +switch Obj.GLOBAL_SOFAConventions + + case 'SimpleFreeFieldHRIR' +disp(['Datebase Name: ' Obj.GLOBAL_DatabaseName]) + disp(' ') + disp(['Measurement details (' Obj.GLOBAL_SOFAConventions '):']); + disp('--------------------'); + disp(['Number of azimuth angles: ' num2str(length(unique(Obj.SourcePosition(:,1))))]); + disp(['Number of elevation angles: ' num2str(length(unique(Obj.SourcePosition(:,2))))]); + disp(['Number of radii: ' num2str(length(unique(Obj.SourcePosition(:,3))))]); + if isfield(Obj.Data,'SamplingRate') + disp(['Sampling Rate: ' num2str(Obj.Data.SamplingRate) ' ' Obj.Data.SamplingRate_Units]) + + end + disp(['Listener Short Name: ' Obj.GLOBAL_ListenerShortName]) + + if size(Obj.ListenerPosition,1)==1 + disp(['Listener Position: ', num2str(Obj.ListenerPosition) ' ' Obj.ListenerPosition_Units]); + else + disp([num2str(size(Obj.ListenerPosition,1)) ' Listener Positions']); + disp([' from ' num2str(Obj.ListenerPosition(1,:)) ' [' Obj.ListenerPosition_Units ']']); + disp([' to ' num2str(Obj.ListenerPosition(end,:)) ' [' Obj.ListenerPosition_Units ']']); + end + + if size(Obj.ListenerView,1)==1 + disp(['Listener View: ', num2str(Obj.ListenerView) ' ' Obj.ListenerView_Units]); + else + disp([num2str(size(Obj.ListenerPosition,1)) ' Listener Views']); + disp([' from ' num2str(Obj.ListenerView(1,:)) ' [' Obj.ListenerView_Units ']']); + disp([' to ' num2str(Obj.ListenerView(end,:)) ' [' Obj.ListenerView_Units ']']); + end + + if size(Obj.ReceiverPosition,1)==1 + disp(['Receiver Position: ', num2str(Obj.ReceiverPosition) ' ' Obj.ReceiverPosition_Units]); + else + disp([num2str(size(Obj.ReceiverPosition,1)) ' Receiver Positions']); + disp([' from ' num2str(Obj.ReceiverPosition(1,:)) ' [' Obj.ReceiverPosition_Units ']']); + disp([' to ' num2str(Obj.ReceiverPosition(end,:)) ' [' Obj.ReceiverPosition_Units ']']); + end + disp(['Receiver Position Type: ' Obj.ReceiverPosition_Type]) + + if size(Obj.SourcePosition,1)==1 + disp(['Source Position: ', num2str(Obj.SourcePosition) ' ' Obj.SourcePosition_Units]); + else + disp([num2str(size(Obj.SourcePosition,1)) ' Source Positions']); + disp([' from ' num2str(Obj.SourcePosition(1,:)) ' [' Obj.SourcePosition_Units ']']); + disp([' to ' num2str(Obj.SourcePosition(end,:)) ' [' Obj.SourcePosition_Units ']']); + end + disp(['Source Position Type: ' Obj.SourcePosition_Type]) + otherwise + % fill with conventions and disp commands if you feel motivated +end + +disp('### end ###') diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..63192cfef57ac8d3a41745d2ce791fcc93ed9e37 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m @@ -0,0 +1,187 @@ +function Obj = SOFAload(fn,varargin) +%SOFALOAD +% Obj = SOFAload(FN) reads the SOFA object OBJ with all data from a SOFA file FN. +% +% FN can point to a remote file (containing '://') or to a local file: +% Remote file: FN will be downloaded to a temporary directory and loaded. +% Local file: If existing, will be loaded. If not existing, it will be downloaded from the internet repository given by SOFAdbURL. For this, FN must begin with the local HRTF directory given by SOFAdbPath. +% +% Obj = SOFAload(FN,'nodata') ignores the "Data." variables and loads metadata only (variables and attributes). +% +% Obj = SOFAload(FN,[START COUNT]) loads only COUNT number of measurements (dimension M) beginning with the index START. For remote files, or local but not existing files, the full file will be downloaded. +% +% Obj = SOFAload(FN,[START1 COUNT1],DIM1,[START2 COUNT2],DIM2,...) loads only COUNT1 number of data in dimension DIM1 beginning with the index START1, COUNT2 number of data in dimension DIM2 with the index START2 and so on. +% +% Obj = SOFAload(FN,...,'nochecks') loads the file but does not perform any checks for correct conventions. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAload +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% ----- Input parameters ------------------------------------------------ +inputargs={}; % for setting flags with SOFAarghelper +pDims=''; % for partial loading +pDimRange=[]; % for partial loading +jj=1; kk=1; ll=1; +for ii=1:length(varargin) + if isnumeric(varargin{ii}) + pDimRange(jj,:)=varargin{ii}; + jj=jj+1; + if ii==1 + inputargs{kk}=varargin{ii}; + kk=kk+1; + end + elseif strfind('MREN',varargin{ii}) + pDims(ll)=varargin{ii}; + ll=ll+1; + elseif strcmp(varargin{ii},'nochecks') + inputargs{kk}=varargin{ii}; + elseif strcmp(varargin{ii},'nodata') + inputargs{kk}=varargin{ii}; + kk=kk+1; + end +end +if ~isempty(pDimRange) && isempty(pDims) + pDims='M'; +end + +% Set flags with SOFAarghelper +definput.keyvals.Index = []; +definput.flags.type = {'data','nodata'}; +definput.flags.data = {'checks','nochecks'}; +[flags,kv] = SOFAarghelper({'Index'},definput,inputargs); + +% Check number of input arguments for partial loading +if ~(length(pDims)==size(pDimRange,1) || isempty(kv.Index)) + error('Missing dimension or range for partial loading'); +end +% Check file name +fn = SOFAcheckFilename(fn); +% Check if local or remote and download if necessary +if strfind(fn,'://') + % remote path: download as temporary + newfn = [tempname '.sofa']; + urlwrite(fn, newfn); +else + newfn = fn; + if ~exist(fn,'file') % file does not exist? + warning('SOFA:load',['File not found: ' strrep(fn,'\','\\')]); + % local path: replace SOFAdbPath by SOFAdbURL, download to SOFAdbPath + if length(fn)>length(SOFAdbPath) % fn is longer than SOFAdbPath? + if strcmp(SOFAdbPath,fn(1:length(SOFAdbPath))) % fn begins with SOFAdbPath + % create dir if not existing + if ~exist(fileparts(newfn),'dir'), + [success,msg] = mkdir(fileparts(newfn)); + if success~=1, error(msg); end + end + webfn = fn(length(SOFAdbPath)+1:end); + webfn(strfind(webfn,'\'))='/'; + webfn = [SOFAdbURL regexprep(webfn,' ','%20')]; + disp(['Downloading ' fn(length(SOFAdbPath)+1:end) ' from ' SOFAdbURL]); + [f,stat] = urlwrite(webfn,fn); + if ~stat + error(['Could not download file: ' webfn]); + end + else % fn not existing and not beginning with SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + else % fn not existing and shorter than SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + end +end + + +%% ----- Load SOFA file -------------------------------------------------- +if flags.do_nodata + Obj = NETCDFload(newfn,'nodata'); +elseif flags.do_data + try + if isempty(kv.Index), + Obj = NETCDFload(newfn,'all'); + else + Obj = NETCDFload(newfn,pDimRange,pDims); + end + catch me + error(['Error loading the file: ' newfn 13 me.message]); + end +end + + +%% ----- Checking of loaded data ----------------------------------------- +% Return if no checks should be performed +if flags.do_nochecks + return; +else + + % ----- Check for SOFA conventions ----- + if ~isfield(Obj,'GLOBAL_Conventions') || ~strcmp(Obj.GLOBAL_Conventions,'SOFA') + error('File is not a valid SOFA file'); + end + if ~isfield(Obj,'GLOBAL_SOFAConventions') + error('Information about SOFA conventions is missing'); + end + try + ObjTemplate = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + if isempty(ObjTemplate), + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + catch + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + + % ----- Check if DataType is present ----- + if ~isfield(Obj,'GLOBAL_DataType') + error('DataType is missing'); + end + + % ----- Check if mandatory variables are present ----- + for field = fieldnames(ObjTemplate)' + field = field{:}; + if ~isfield(Obj,field) + Obj.(field) = ObjTemplate.(field); + if ~strfind(field,'_') % if `_` is missing it is a dimension + Obj.API.Dimensions.(field) = ObjTemplate.API.Dimensions.(field); + end + warning('SOFA:load',[field ' was missing, set to default']); + end + end + + % ---- If data loaded, check for correct data format ----- + if ~flags.do_nodata + if ~isfield(Obj,'Data') + error('Data is missing'); + end + for field = fieldnames(ObjTemplate.Data)' + field = field{:}; + if ~isfield(Obj.Data,field) + Obj.Data.(field) = ObjTemplate.Data.(field); + Obj.API.Dimensions.Data.(field) = ... + ObjTemplate.API.Dimensions.Data.(field); + warning('SOFA:load',['Data.' field ' was missing, set to default']); + end + end + Obj = SOFAupdateDimensions(Obj); + end + + % Remove undesired attribute of NetCDF files, if existing + if isfield(Obj,'GLOBAL__NCProperties'), Obj=rmfield(Obj,'GLOBAL__NCProperties'); end + + % ----- Ensure backwards compatibility ----- + % TODO: is the while loop necessary, or could be handled just by calling + % SOFAupgradeConventions(Obj) once? + modified = 1; + while modified + [Obj,modified] = SOFAupgradeConventions(Obj); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..36c5e5fbcdec7da9c6dd3157379052a793c274cd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m @@ -0,0 +1,154 @@ +function [C, log] = SOFAmerge(A,B) +%SOFAmerge +% [C, log] = SOFAmerge(A, B) merges the SOFA objects A and B to a single one, C. +% +% A and B are structs containing the data and meta. A and B +% must be of the same SOFA conventions. +% +% C is a struct containing merged data +% log contains log data + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupdateDimensions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +if ~strcmp(A.GLOBAL_SOFAConventions,B.GLOBAL_SOFAConventions) + error('Both SOFA objects must use the same SOFA conventions'); +end +if A.API.N~=B.API.N + error('Data size of both SOFA objects must be the same'); +end +Def = SOFAdefinitions; +log={''}; +OC = SOFAgetConventions(A.GLOBAL_SOFAConventions,'a'); + +%% Update dimensions +A=SOFAupdateDimensions(A); +B=SOFAupdateDimensions(B); + +%% create field names which have to be checked +C=rmfield(B,{'API','Data'}); +if isfield(C,'PRIVATE'), C=rmfield(C,'PRIVATE'); end +Bf=fieldnames(C); + +%% Copy and merge metadata variables +C=A; +for ii=1:size(Bf,1) + if ~isfield(A,Bf{ii}) + C.(Bf{ii}) = B.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.(Bf{ii}),B.(Bf{ii})), + C.(Bf{ii}) = B.(Bf{ii}); % content the same, no conflict + else + switch Bf{ii} + case 'GLOBAL_TimeCreated' % use the oldest date + dateNew=datenum(A.GLOBAL_TimeCreated,Def.dateFormat); + if datenum(B.GLOBAL_TimeCreated,Def.dateFormat)<dateNew, dateNew=datenum(B.GLOBAL_TimeCreated,Def.dateFormat); end; + C.(Bf{ii}) = datestr(dateNew,Def.dateFormat); + log{end+1}=[Bf{ii} ' set to ' C.(Bf{ii})]; + case 'GLOBAL_TimeModified' % now + C.(Bf{ii}) = datestr(now,Def.dateFormat); + log{end+1}=[Bf{ii} ' updated']; + otherwise + C.(Bf{ii}) = [A.(Bf{ii}) '; ' B.(Bf{ii})]; % concatate [A; B] + log{end+1}=[Bf{ii} ' merged']; + end + end + else % a variable + if isfield(OC.API.Dimensions, Bf{ii}) % is a known variable? + AExp=SOFAexpand(A,Bf{ii}); + BExp=SOFAexpand(B,Bf{ii}); + dim=strfind(AExp.API.Dimensions.(Bf{ii}),'M'); + if isempty(dim), + error([Bf{ii} ' can not be merged because it does not depend on M']); + end + C.(Bf{ii})=cat(dim,AExp.(Bf{ii}),BExp.(Bf{ii})); + log{end+1}=[Bf{ii} ' expanded and merged']; + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.(Bf{ii}),'M'); + if ~isempty(dim), + C.(Bf{ii})=cat(dim,A.(Bf{ii}),B.(Bf{ii})); % depends on M, merge + log{end+1}=[Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.(Bf{ii})==B.(Bf{ii}))==1, + C.(Bf{ii})=A.(Bf{ii}); + log{end+1}=[Bf{ii} ' identical']; + else + error([Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Copy and merge Data variables +Bf=fieldnames(B.Data); +for ii=1:size(Bf,1) + if ~isfield(A.Data,Bf{ii}) + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.Data.(Bf{ii}),B.Data.(Bf{ii})), + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % content the same, no conflict + else + C.Data.(Bf{ii}) = [A.Data.(Bf{ii}) '; ' B.Data.(Bf{ii})]; % concatate [A; B] + log{end+1}=['Data.' Bf{ii} ' merged']; + end + else % a variable in Data + if isfield(OC.API.Dimensions.Data,Bf{ii}) % is a known variable? + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); % is a matrix + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if all(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Update the new dimensions and finish +C=SOFAcompact(C); +C=SOFAupdateDimensions(C); +if length(log)>1, log=log(2:end); else log={}; end; + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m new file mode 100644 index 0000000000000000000000000000000000000000..7541ffac9f25356c5ccfc7e8e15dc9b92e6cd945 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m @@ -0,0 +1,463 @@ +function SOFAplotGeometry(Obj,varargin) +% SOFAplotGeometry(Obj) plots the geometry found in the Obj. +% +% SOFAplotGeometry(Obj, index) plots the geometry for the measurements +% given in the index. +% +% Supported conventions: +% SimpleFreeFieldHRIR +% SimpleFreeFieldHRTF +% SingleRoomDRIR +% FreeFieldDirectivityTF +% some special cases of GeneralFIR. +% +% Parameter +% 'index' measurement to be plotted. Default: 1:Obj.API.M +% 'normalize' normalize view and up vectors +% 'SHorder' order of spherical harmonics +% 'SHm' m of shperical harmonics +% 'normalize' normalize view and up vectors +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: bug fixed when extracting LU (listener up) coordinates (28.12.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.keyvals.index=1:Obj.API.M; +definput.keyvals.shorder=Inf; +definput.keyvals.shm=Inf; +definput.flags.normalize={'normalize'}; +argin=varargin; +for ii=1:length(argin) + if ischar(argin{ii}), argin{ii}=lower(argin{ii}); end +end +[flags,kv] = SOFAarghelper({'index','shorder','shm'},definput,argin); +index = kv.index; +SHorder=kv.shorder; +SHm=kv.shm; +flags.do_normalize = flags.normalize; + +if any(index > Obj.API.M) + error(['Index out of range. Only ', num2str(Obj.API.M), ... + ' measurement(s) performed.']) +elseif any(index < 1) + error('Choose index to be >= 1.') +end + +switch Obj.GLOBAL_SOFAConventions +%% + case {'SimpleFreeFieldHRTF','SimpleFreeFieldHRIR','SingleRoomDRIR','FreeFieldDirectivityTF','GeneralFIR','GeneralTFE','FreeFieldHRIR','FreeFieldHRTF','GeneralTF-E'} + % Expand entries to the same number of measurement points + Obj = SOFAexpand(Obj); + % See if the room geometry is specified + if strcmpi(Obj.GLOBAL_RoomType,'shoebox') + x = min(Obj.RoomCornerA(1), Obj.RoomCornerB(1)); + xd = max(Obj.RoomCornerA(1), Obj.RoomCornerB(1)); + y = min(Obj.RoomCornerA(2), Obj.RoomCornerB(2)); + yd = max(Obj.RoomCornerA(2), Obj.RoomCornerB(2)); + w = xd - x; + h = yd - y; + figure('Position',[1 1 w*1.2 h]*100); + box on; hold on; + % plot the room + rectangle('Position',[x y w h]); + else + figure; hold on; + end + + legendEntries = []; + title(sprintf('%s, %s',Obj.GLOBAL_SOFAConventions,Obj.GLOBAL_RoomType)); + % Get ListenerPosition, ReceiverPosition, SourcePosition, and + % EmitterPosition + % NOTE: ListenerPosition is set to [0 0 0] for SimpleFreeFieldHRIR + LP = SOFAconvertCoordinates(Obj.ListenerPosition(index,:),Obj.ListenerPosition_Type,'cartesian'); + if ~(strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics')) + if size(Obj.ReceiverPosition,3)==1, idx=1; else idx=index; end + RP = SOFAconvertCoordinates(Obj.ReceiverPosition(:,:,idx),Obj.ReceiverPosition_Type,'cartesian'); + end + if size(Obj.SourcePosition,1)==1, idx=1; else idx=index; end + SP = SOFAconvertCoordinates(Obj.SourcePosition(idx,:),Obj.SourcePosition_Type,'cartesian'); + if ~(strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics')) + if size(Obj.EmitterPosition,3)==1, idx=1; else idx=index; end + EP = SOFAconvertCoordinates(Obj.EmitterPosition(:,:,idx),Obj.EmitterPosition_Type,'cartesian'); + end + if isfield(Obj,'ListenerView') + if size(Obj.ListenerView,1)==1, idx=1; else idx=index; end + LV = SOFAconvertCoordinates(Obj.ListenerView(idx,:),Obj.ListenerView_Type,'cartesian'); + end + if isfield(Obj,'ListenerUp') + try + if size(Obj.ListenerUp,1)==1, idx=1; else idx=index; end + LU = SOFAconvertCoordinates(Obj.ListenerUp(idx,:),Obj.ListenerUp_Type,'cartesian'); + catch + % if listerUp_type is not defined try using listenerView_type + % instead + if size(Obj.ListenerUp,1)==1, idx=1; else idx=index; end + LU = SOFAconvertCoordinates(Obj.ListenerUp(idx,:),Obj.ListenerView_Type,'cartesian'); + end + end + if isfield(Obj,'SourceView') + if size(Obj.SourceView,1)==1, idx=1; else idx=index; end + SV = SOFAconvertCoordinates(Obj.SourceView(idx,:),Obj.SourceView_Type,'cartesian'); + end + if isfield(Obj,'SourceUp') + try + if size(Obj.SourceUp,1)==1, idx=1; else idx=index; end + SU = SOFAconvertCoordinates(Obj.SourceUp(idx,:),Obj.SourceUp_Type,'cartesian'); + catch + if size(Obj.SourceUp,1)==1, idx=1; else idx=index; end + SU = SOFAconvertCoordinates(Obj.SourceUp(idx,:),Obj.SourceView_Type,'cartesian'); + end + end + % Use only unique listener and source positons + caseString = ''; + uniquePoints = [LP SP]; + if exist('LV') + uniquePoints = [uniquePoints LV]; + caseString = strcat(caseString , 'LV'); + end + if exist('LU') + uniquePoints = [uniquePoints LU]; + caseString = strcat(caseString, 'LU'); + end + if exist('SV') + uniquePoints = [uniquePoints SV]; + caseString = strcat(caseString, 'SV'); + end + if exist('SU') + uniquePoints = [uniquePoints SU]; + caseString = strcat(caseString, 'SU'); + end + + uniquePoints = unique(uniquePoints,'rows'); + switch caseString + case '' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + case 'LV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + case 'LVLU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); +% LU = uniquePoints(:,7:9); % I think this was a bug (miho) + LU = uniquePoints(:,10:12); + case 'LVLUSV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + LU = uniquePoints(:,10:12); + SV = uniquePoints(:,13:15); + case 'SV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + SV = uniquePoints(:,7:9); + case 'SVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + SV = uniquePoints(:,7:9); + SU = uniquePoints(:,10:12); + case 'LVSV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + SV = uniquePoints(:,10:12); + case 'LVSVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + SV = uniquePoints(:,10:12); + SU = uniquePoints(:,13:15); + case 'LVLUSVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + LU = uniquePoints(:,10:12); + SV = uniquePoints(:,13:15); + SU = uniquePoints(:,16:18); + otherwise + error('This SOFAConventions is not supported for plotting'); + end + + % Plot ListenerPosition + legendEntries(end+1) = plot3(LP(:,1),LP(:,2),LP(:,3),'ro','MarkerFaceColor','r','MarkerSize',5); + if strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics') + maxSHorder = sqrt(Obj.API.R)-1; + % set SHorder to max if user didn't specify it + if isinf(SHorder) + SHorder = maxSHorder; + end + % check if chosen SHorder is possible + if SHorder > maxSHorder + error(['Chosen SHorder not possibile, only orders up to ', ... + num2str(maxSHorder), ' possible.']) + elseif SHorder < 0 + error('Chosen SHorder not possibile, as it must be positive.') + end + x0 = Obj.ListenerPosition(1,1); + y0 = Obj.ListenerPosition(1,2); + z0 = Obj.ListenerPosition(1,3); + + % check for m given by the user and if it is possible + if isinf(SHm) + % if not set to some value + SHm = -floor(1/2 * SHorder); + elseif abs(SHm) > SHorder + error(['Chosen SHm not possibile, must be in range of abs(', ... + num2str(SHorder), ').']) + end + % if possibile set SHmForPlotting + SHmForPlotting = power(SHorder,2)+SHorder+SHm+1; + + [X,Y,Z] = sphere(50); + [azi_rad,elev_rad,~] = cart2sph(X,Y,Z); + azi_length =size(azi_rad,1); + elev_length=size(elev_rad,1); + azi= azi_rad/pi*180; + elev = elev_rad/pi*180; + azi = azi(:); + elev = elev(:); + + S = sph2SH([azi,elev], SHorder); + S = S(:,SHmForPlotting); + S = reshape(S,[azi_length,elev_length]); + + r_sphere = 0.7*max(max(S))*randi(2,size(S)); + r = abs(S) + r_sphere; + + [D_x,D_y,D_z] = sph2cart(azi_rad,elev_rad,abs(r)); + legendEntries(end+1) = surf(D_x+x0,D_y+y0,D_z+z0,Y,'LineStyle','none','FaceAlpha',0.09); +% elseif strcmpi(Obj.ReceiverPosition_Type,'spherical') +% S = sqrt(Obj.API.R-1); +% x0 = Obj.ListenerPosition(1,1); +% y0 = Obj.ListenerPosition(1,2); +% theta = -pi : 0.01 : pi; +% r = 1; +% phi = sin(S*theta); +% phi_negativ = sin(-S*theta); +% +% [x,y] = pol2cart(theta,(r*(1+ abs(phi)+ abs(phi_negativ)))./3); +% legendEntries(end+1)=plot(x+x0,y+y0,'LineStyle','--','Color',[0.741 0.747 0.741]); +% +% % text(x0,y0+r,['Order: ',num2str(S)],'HorizontalAlignment',... +% % 'center','VerticalAlignment','bottom') + + else + % Plot ReceiverPositon (this is plotted only for the first ListenerPosition) + if ndims(RP)>2 + % If ReceiverPosition has more than two dimensions reduce it to the first + % ListenerPosition + RP = shiftdim(RP,2); + RP = squeeze(RP(1,:,:)); + RP = reshape(RP,[size(Obj.ReceiverPosition,1), Obj.API.C]); + end + legendEntries(end+1) = plot3(LP(1,1)+RP(1,1), LP(1,2)+RP(1,2), LP(1,3)+RP(1,3),'r*','MarkerSize',8); + for ii=2:size(RP,1) + plot3(LP(1,1)+RP(ii,1), LP(1,2)+RP(ii,2), LP(1,3)+RP(ii,3),'r*','MarkerSize',8); + end + end + % Plot SourcePosition + legendEntries(end+1)=plot3(SP(:,1),SP(:,2),SP(:,3),'bd','MarkerSize',7); + % Plot EmitterPositions depending on Type + if strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics') + maxSHorder = sqrt(Obj.API.E)-1; + % set SHorder to max if user didn't specify it + if isinf(SHorder) + SHorder = maxSHorder; + end + % check if chosen SHorder is possible + if SHorder > maxSHorder + error(['Chosen SHorder not possibile, only orders up to ', ... + num2str(maxSHorder), ' possible.']) + elseif SHorder < 0 + error('Chosen SHorder not possibile, as it must be positive.') + end + x0 = Obj.SourcePosition(1,1); + y0 = Obj.SourcePosition(1,2); + z0 = Obj.SourcePosition(1,3); + + % check for m given by the user + if isinf(SHm) + SHm = -floor(1/2 * SHorder); + elseif abs(SHm) > SHorder + error(['Chosen SHm not possibile, must be in range of abs(', ... + num2str(SHorder), ').']) + end + % if possibile set SHmForPlotting + SHmForPlotting = power(SHorder,2)+SHorder+SHm+1; + + [X,Y,Z] = sphere(50); + [azi_rad,elev_rad,~] = cart2sph(X,Y,Z); + azi_length =size(azi_rad,1); + elev_length=size(elev_rad,1); + azi= azi_rad/pi*180; + elev = elev_rad/pi*180; + azi = azi(:); + elev = elev(:); + + S = sph2SH([azi,elev], SHorder); + S = S(:,SHmForPlotting); + S = reshape(S,[azi_length,elev_length]); + + r_sphere = 0.7*max(max(S))*randi(2,size(S)); + r = abs(S) + r_sphere; + + [D_x,D_y,D_z] = sph2cart(azi_rad,elev_rad,abs(r)); + legendEntries(end+1) = surf(D_x+x0,D_y+y0,D_z+z0,Y,'LineStyle','none','FaceAlpha',0.09); + +% elseif strcmpi(Obj.EmitterPosition_Type,'spherical') +% S = sqrt(Obj.API.R-1); +% x0 = Obj.SourcePosition(1,1); +% y0 = Obj.SourcePosition(1,2); +% theta = -pi : 0.01 : pi; +% r = 1; +% phi = sin(S*theta); +% phi_negativ = sin(-S*theta); +% +% [x,y] = pol2cart(theta,(r*(1+ abs(phi)+ abs(phi_negativ)))./3); +% legendEntries(end+1)=plot(x+x0,y+y0,'LineStyle','--','Color',[0.741 0.747 0.741]); +% +% % text(x0,y0+r,['Order: ',num2str(S)],'HorizontalAlignment',... +% % 'center','VerticalAlignment','bottom') + + else + % Plot EmitterPosition + if ndims(EP)>2 + % If EmitterPosition has more than two dimensions reduce it to the first + % ListenerPosition + EP = shiftdim(EP,2); + EP = squeeze(EP(1,:,:)); + EP = reshape(EP,[size(Obj.EmitterPosition,1), Obj.API.C]); + end + % plot Emitters for first Source + legendEntries(end+1) = plot3(SP(1,1)+EP(1,1), SP(1,2)+EP(1,2), SP(1,3)+EP(1,3),'b+','MarkerSize',8); + for ii=2:size(EP,1) + plot3(SP(1,1)+EP(ii,1), SP(1,2)+EP(ii,2), SP(1,3)+EP(ii,3),'b+','MarkerSize',8); + end + % plot all Emitters for each Source + for jj=2:size(SP,1) + for ii=1:size(EP,1) + plot3(SP(jj,1)+EP(ii,1), SP(jj,2)+EP(ii,2), SP(jj,3)+EP(ii,3),'b+'); + end + end + end + if exist('LV','var') + % Plot ListenerView + LV=unique(LV,'rows'); + for ii = 2:size(LV,1) + % Scale size of ListenerView vector smaller + if flags.do_normalize + LV(ii,:) = LV(ii,:)./norm(LV(ii,:)); + end + % Plot line for ListenerView vector + quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LV(ii,1),LV(ii,2),LV(ii,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if flags.do_normalize + LV(1,:) = LV(1,:)./norm(LV(1,:)); + end + legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LV(1,1),LV(1,2),LV(1,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if exist('LU','var') + LU=unique(LU,'rows'); + for ii = 2:size(LU,1) + if flags.do_normalize + LU(ii,:) = LU(ii,:)./norm(LU(ii,:)); + end + quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LU(ii,1),LU(ii,2),LU(ii,3),0,'AutoScale','off','Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LU(ii,1),LU(ii,2),LU(ii,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LV(ii,1),LV(ii,2),LV(ii,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if flags.do_normalize + LU(1,:) = LU(1,:)./norm(LU(1,:)); + end + legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LU(1,1),LU(1,2),LU(1,3),0,'AutoScale','off','Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LU(1,1),LU(1,2),LU(1,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LV(1,1),LV(1,2),LV(1,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if exist('SV','var') + SV=unique(SV,'rows'); + % Plot ListenerView + for ii = 2:size(SV,1) + % Scale size of ListenerView vector smaller + if flags.do_normalize + SV(ii,:) = SV(ii,:)./norm(SV(ii,:)); + end + % Plot line for ListenerView vector + quiver3(SP(ii,1),SP(ii,2),SP(ii,3),SV(ii,1),SV(ii,2),SV(ii,3),0,... + 'AutoScale','off',... + 'Color',[0 0 1],'MarkerFaceColor',[0 0 1]); + end + if flags.do_normalize + SV(1,:) = SV(1,:)./norm(SV(1,:)); + end + legendEntries(end+1) = quiver3(SP(1,1),SP(1,2),SP(1,3),SV(1,1),SV(1,2),SV(1,3),0,... + 'AutoScale','off',... + 'Color',[0 0 1],'MarkerFaceColor',[0 0 1]); + end + if exist('SU','var') + SU=unique(SU,'rows'); + for ii = 2:size(SU,1) + if flags.do_normalize + SU(ii,:) = SU(ii,:)./norm(SU(ii,:)); + end + quiver3(SP(ii,1),SP(ii,2),SP(ii,3),SU(ii,1),SU(ii,2),SU(ii,3),0,... + 'AutoScale','off',... + 'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); + end + if flags.do_normalize + SU(1,:) = SU(1,:)./norm(SU(1,:)); + end + legendEntries(end+1) = quiver3(SP(1,1),SP(1,2),SP(1,3),SU(1,1),SU(1,2),SU(1,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); + end + % create legend + legendDescription = {'ListenerPosition'}; + if (strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics')) + legendDescription{end+1} = ['Receiver (order: ', num2str(S_R) ,')']; + else + legendDescription{end+1} = 'ReceiverPosition'; + end + legendDescription{end+1} ='SourcePosition'; + if (strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics')) + legendDescription{end+1} = ['Emitter (order: ', num2str(SHorder),', m: ', num2str(SHm),')']; + else + legendDescription{end+1} = 'EmitterPosition'; + end + + if exist('LV','var') + legendDescription{end+1} = 'ListenerView'; + end + if exist('LU','var') + legendDescription{end+1} = 'ListenerUp'; + end + if exist('SV','var') + legendDescription{end+1} = 'SourceView'; + end + if exist('SU','var') + legendDescription{end+1} = 'SourceUp'; + end + legend(legendEntries,legendDescription,'Location','NorthEastOutside'); + xlabel(['X / ' Obj.ListenerPosition_Units]); + ylabel(['Y / ' Obj.ListenerPosition_Units]); + zlabel(['Z / ' Obj.ListenerPosition_Units]); + + otherwise + error('This SOFAConventions is not supported for plotting'); +end + +% Set fixed aspect ratio +axis equal; +% Add a little bit extra space at the axis +axisLimits = axis(); +paddingSpace = 0.2 * max(abs(axisLimits(:))); +axisLimits([1 3]) = axisLimits([1 3]) - paddingSpace; +axisLimits([2 4]) = axisLimits([2 4]) + paddingSpace; +axis(axisLimits); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..41f96a7d3cab820f164e0ac99fbf1cbb198598ea --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m @@ -0,0 +1,506 @@ +function [M,meta,h]=SOFAplotHRTF(Obj,type,varargin) +% SOFAplotHRTF(OBJ, TYPE, R, DIR, COLOR) plots the R receiver of HRTFs given in OBJ. +% The following TYPEs are supported: +% 'EtcHorizontal' energy-time curve in the horizontal plane (+/- THR) +% 'EtcMedian' energy-time curve in the median plane (+/- THR) +% 'MagHorizontal' magnitude spectra in the horizontal plane (+/- THR) +% 'MagMedian' magnitude spectra in the median plane (+/- THR) +% 'MagSpectrum' single magnitude spectrum for direction(s) DIR in COLOR +% 'MagSagittal' magnitude spectra in a sagittal plane specified by OFFSET +/- THR +% 'ITDhorizontal' interaural time delay in the horizontal plane (not +% supported in Octave) +% +% More options are available by SOFAplotHRTF(Obj,type,parameter,value) +% +% Parameters: +% 'receiver' receiver to be plotted. Default: 1 +% 'dir' fixes the positions to be plotted: +% [azi]: shows all direction for that azimuth +% [azi, ele]: shows all distances for that direction +% [azi, ele, distance]: shows only that position +% default: [0,0] +% 'offset' chooses a plane to be plotted. Default: 0 deg. +% 'thr' threshold for selecting positions around a plane. Default: 2 deg. +% 'floor' lowest amplitude shown (dB). Default: -50 dB. +% 'convert' convert to TF domain. Function should automatically choose if neccessary. Default: 0 if conversion is not necessary; 1 if conversion is neccessary. +% +% Additionally, 'b', 'r', 'g', etc. can be used for plotting in color +% as used by PLOT. +% +% +% Supported conventions: +% SimpleFreeFieldHRIR +% SimpleFreeFieldHRSOS +% SimpleFreeFieldHRTF +% SHFreeFieldHRTF +% some special cases of GeneralTF, GeneralTF-E. +% +% [M,meta,h]=SOFAplotHRTF... returns the matrix M and meta information about displayed in the figure. +% h is the handle of the plot. meta.idx is the index to the vectors actually plotted. +% +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: type ITDhorizontal added and updated (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: dependency on function 'npi2pi' removed (required toolbox in Matlab; in Octave not supported; outdated anyway) (08.02.2022) +% #Author: Michael Mihocic: keyvalue 'R'/'r' renamed to 'receiver' (10.05.2022) +% #Author: Michael Mihocic: 'do not convert' option enabled for SimpleFreeFieldHRTF convention; +% global title only displayed if 'Obj.GLOBAL_Title' not empty (30.05.2022) +% #Author: Michael Mihocic: plotting simplefreefieldhrtf fixed (in Octave); titles fixed when plotting magspectrum (02.06.2022) +% #Author: Michael Mihocic: plotting improved when data is available in TF format (more stable, no conversions by default); +% figure titles improved (04.07.2022) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% for backward compatibility (type as position-dependent input parameter) +if nargin == 3 && ischar(type) && isscalar(varargin{1}) +% varargin = flipud(varargin(:)); + R = varargin{1}; + flags.do_normalize=1; + dir=[0,0]; + color='b'; + thr=2; + offset=0; + noisefloor=-50; +% convert=1; more comples differing below: + + if exist('OCTAVE_VERSION','builtin') + % We're in Octave + if ismember(type,{'MagHorizontal','MagMedian','MagSpectrum','MagSagittal'}) && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) + % frequency domain input data only; for Octave the list has to be extended manually because 'contains' is not available + convert = 0; + else + convert = 1; + end + else + % We're in Matlab + if contains(lower(type),'mag') && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) + % frequency domain input data only + convert = 0; + else + convert = 1; + end + end + +else + definput.keyvals.receiver=1; + definput.keyvals.dir=[0,0]; + definput.keyvals.thr=2; + definput.keyvals.offset=0; + definput.keyvals.floor=-50; + definput.flags.color={'b','r','k','y','g','c','m'}; + definput.flags.level={'normalize','absolute'}; + definput.keyvals.convert=1; + argin=varargin; + for ii=1:length(argin) + if ischar(argin{ii}), argin{ii}=lower(argin{ii}); end + end + [flags,kv] = SOFAarghelper({'receiver','dir','thr','offset','floor'},definput,argin); + R = kv.receiver; + dir = kv.dir; + thr=kv.thr; + color = flags.color; + offset = kv.offset; + noisefloor=kv.floor; + convert=kv.convert; % force convert or not + +% if exist('OCTAVE_VERSION','builtin') +% % We're in Octave +% if ismember(type,{'MagHorizontal','MagMedian','MagSpectrum','MagSagittal'}) && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) +% % frequency domain input data only; for Octave the list has to be extended manually because 'contains' is not available +% convert=kv.convert; +% else +% convert = 1; +% end +% else +% % We're in Matlab +% if contains(lower(type),'mag') && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) +% % frequency domain input data only +% convert=kv.convert; +% else +% convert = 1; +% end +% end + +end + +meta=[]; + +if convert == 1 + %% Convert data to FIR + Obj=SOFAconvertConventions(Obj); + fs=Obj.Data.SamplingRate; + + %% check if receiver selection is possible + if R > size(Obj.Data.IR,2) + error(['Choosen receiver out of range. Only ', num2str(size(Obj.Data.IR,2)), ' receivers recorded.']) + end + titlepostfix=' (converted to IR)'; +else + %% check if receiver selection is possible + if R > size(Obj.Data.Real,2) + error(['Choosen receiver out of range. Only ', num2str(size(Obj.Data.Real,2)), ' receivers recorded.']) + end + titlepostfix=''; +end +if isfield(Obj, 'GLOBAL_Title') && isempty(Obj.GLOBAL_Title) == 0 + titleprefix = [Obj.GLOBAL_Title ': ']; +else + titleprefix = ''; +end + + +%% Convert to spherical if cartesian +if strcmp(Obj.SourcePosition_Type,'cartesian') +% % Obj2=Obj; % compare to old method (Obj2) + for ii=1:Obj.API.M + [Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)]=cart2sph(Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)); +% [Obj2.SourcePosition(ii,1),Obj2.SourcePosition(ii,2),Obj2.SourcePosition(ii,3)]=cart2sph(Obj2.SourcePosition(ii,1),Obj2.SourcePosition(ii,2),Obj2.SourcePosition(ii,3)); + Obj.SourcePosition(ii,2)=rad2deg(Obj.SourcePosition(ii,2)); +% Obj2.SourcePosition(ii,2)=rad2deg(Obj2.SourcePosition(ii,2)); + Obj.SourcePosition(ii,1)=rad2deg(Obj.SourcePosition(ii,1)); +% Obj2.SourcePosition(ii,1)=rad2deg(Obj2.SourcePosition(ii,1)); + Obj.SourcePosition(ii,1)=mywrapTo180(Obj.SourcePosition(ii,1)); +% Obj2.SourcePosition(ii,1)=npi2pi(Obj2.SourcePosition(ii,1),'degrees'); % requires Mapping toolbox in Matlab + end + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degrees'; +end + +%% Plot according to the type +switch lower(type) + % Energy-time curve (ETC) in the horizontal plane + case 'etchorizontal' + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,R,:))); + pos=Obj.SourcePosition; + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,R)); + meta.idx=idx; + M2=noisefloor*ones(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + [azi,i]=sort(pos(:,1)); + M=M2(i,:); + if flags.do_normalize + M=M-max(max(M)); + end + M(M<=noisefloor)=noisefloor; + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.azi = azi; + h=surface(meta.time,azi,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Azimuth (deg)'); + title([titleprefix 'receiver: ' num2str(R)],'Interpreter','none'); + + % Magnitude spectrum in the horizontal plane + case 'maghorizontal' + pos=Obj.SourcePosition; % copy pos to temp. variable + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; % find horizontal plane + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); % find indices + pos=pos(idx,:); % truncate pos + meta.idx=idx; + if convert == 1 % converted + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + if flags.do_normalize + M=M-max(max(M)); % normalize + end + + M(M<noisefloor)=noisefloor; + [azi,i]=sort(pos(:,1)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.azi = azi; +% figure; + h=surface(meta.freq,azi,M(:,:)); + + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [azi,i]=sort(pos(:,1)); + M=M(i,:); +% figure; + + h=surface(Obj.N',azi,M); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Azimuth (deg)'); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magmedian' + azi=0; + pos=Obj.SourcePosition; + idx0=find(abs(pos(:,1))>90); + pos(idx0,2)=180-pos(idx0,2); + pos(idx0,1)=180-pos(idx0,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + pos=pos(idx,:); + meta.idx=idx; % PM: TODO: check if the correct index + + if convert == 1 % converted + + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + + h=surface(meta.freq,ele,M(:,:)); + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); +% figure; + h=surface(Obj.N',ele,M); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Elevation (deg)'); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magsagittal' + + [lat,pol]=sph2hor(Obj.SourcePosition(:,1),Obj.SourcePosition(:,2)); + pos=[lat pol]; + idx=find(pos(:,1)<(offset+thr) & pos(:,1)>(offset-thr)); + pos=pos(idx,:); + meta.idx=idx; + + if convert == 1 % converted + + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + h=surface(meta.freq,ele,M(:,:)); + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + h=surface(Obj.N',ele,M(:,:)); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Polar angle (deg)'); + title([titleprefix 'receiver: ' num2str(R) '; Lateral angle: ' num2str(offset) 'deg' titlepostfix],'Interpreter','none'); + + + % ETC in the median plane + case 'etcmedian' +% noisefloor=-50; + azi=0; + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,R,:))); + pos=Obj.SourcePosition; + idx0=find(abs(pos(:,1))>90); + pos(idx0,2)=180-pos(idx0,2); + pos(idx0,1)=180-pos(idx0,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + meta.idx=idx; % PM: TODO: Check if the correct index + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,R)); + M2=zeros(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + if flags.do_normalize + M=M2-max(max(M2)); + else + M = M2; + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.ele = ele; + h=surface(meta.time,ele,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Elevation (deg)'); + title([titleprefix 'receiver: ' num2str(R)],'Interpreter','none'); + + case 'magspectrum' + pos=round(Obj.SourcePosition*10)/10; + switch size(dir,2) + case 1 + aziPos = pos(:,1); + aziDir=dir(:,1); + aziComp = intersect(aziPos,aziDir,'rows'); + idx= find(ismember(aziPos,aziComp,'rows')); + case 2 + aziPos = pos(:,1); + aziDir=dir(:,1); + elePos = pos(:,2); + eleDir=dir(:,2); + aziComp = intersect(aziPos,aziDir,'rows'); + eleComp = intersect(elePos,eleDir,'rows'); + idx=find(ismember(aziPos,aziComp,'rows') & ... + ismember(elePos,eleComp,'rows')); + otherwise + aziPos = pos(:,1); + aziDir=dir(:,1); + elePos = pos(:,2); + eleDir=dir(:,2); + rPos = pos(:,3); + rDir=dir(:,3); + aziComp = intersect(aziPos,aziDir,'rows'); + eleComp = intersect(elePos,eleDir,'rows'); + rComp = intersect(rPos,rDir,'rows'); + idx=find(ismember(aziPos,aziComp,'rows') & ... + ismember(elePos,eleComp,'rows') & ismember(rPos,rComp,'rows')); + end + if isempty(idx), error('Position not found'); end + meta.idx=idx; + + if convert == 1 % convert + IR=squeeze(Obj.Data.IR(idx,R,:)); + if length(idx) > 1 + M=20*log10(abs(fft(IR')))'; + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + h=plot(0:fs/2/size(M,2):(size(M,2)-1)*fs/2/size(M,2),M); + for ii=1:length(idx) + labels{ii}=['#' num2str(idx(ii)) ': (' num2str(pos(idx(ii),1)) ', ' num2str(pos(idx(ii),2)) ')']; + end + legend(labels); + else % only one curve + hM=20*log10(abs(fft(IR))); + M=hM(1:floor(length(hM)/2)); + hold on; + h=plot(0:fs/2/length(M):(length(M)-1)*fs/2/length(M),M,color,... + 'DisplayName',['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + legend; + end + xlim([0 fs/2]); + titlepostfix=' (converted to IR)'; + else + + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + + if length(idx) > 1 + h=plot(Obj.N',M); + for ii=1:length(idx) + labels{ii}=['#' num2str(idx(ii)) ': (' num2str(pos(idx(ii),1)) ', ' num2str(pos(idx(ii),2)) ')']; + end + legend(labels); + else + hold on; + h=plot(Obj.N',M,color,... + 'DisplayName',['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + legend; + end + titlepostfix=''; + end + ylabel('Magnitude (dB)'); + xlabel('Frequency (Hz)'); + ylim([max(max(M))+noisefloor-10 max(max(M))+10]); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Interaural time delay in the horizontal plane + case 'itdhorizontal' + + if exist('OCTAVE_VERSION','builtin') + warning('Command ''polarplot'' not supported by Octave (yet)!') + else + [itd, ~] = SOFAcalculateITD(Obj, 'time'); + pos = Obj.SourcePosition; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); + itd = itd(idx); + meta.idx=idx; + [pos, idx_sort] = sort(pos(idx,1)); + itd = itd(idx_sort); + angles = deg2rad(pos); + %figure('Renderer', 'painters', 'Position', [10 10 700 450]); + polarplot(angles, itd, 'linewidth', 1.2); + ax = gca; + ax.ThetaDir = 'counterclockwise'; + ax.ThetaZeroLocation = 'top'; + rticks([max(itd)*2/3, max(itd)]); + rticklabels({[num2str(round(max(itd)*2/3*1e6,1)) ' ' char(181) 's'],... + [num2str(round(max(itd)*1e6,1)) ' ' char(181) 's']}); + thetaticks(0:30:330) + thetaticklabels({'0�', '30�', '60�', '90�', '120�', '150�', '180�', ... + '210�', '240�','270�', '300�', '330�'}); + grid on; + end + + otherwise + error([type , ' no supported plotting type.']) +end + + +% function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +% if rem(N,2)==0 +% f=[c; flipud(conj(c(2:end-1,:)))]; +% else +% f=[c; flipud(conj(c(2:end,:)))]; +% end +% f=real(ifft(f,N,1)); +% end + +function newangle = mywrapTo180(angle) + % transfer to range -180:180 + newangle = mod(angle+360, 360); + if newangle > 180 + newangle = newangle-360; + end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..f34eb4981fe97bd882ed2beb59e3eed0d205eb83 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m @@ -0,0 +1,32 @@ +function Obj = SOFAremoveVariable(Obj,Name) +%SOFAremoveVariable +% Obj = SOFAremoveVariable(Obj,Name) removes the user-defined variable +% from the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). +% +% + +% #Author: Piotr Majdak: adapted from SOFAaddVariable (19.06.2019) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAremoveVariable +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +switch Name + case {'API','PRIVATE','GLOBAL','PRIVATE','Data'} + error('This variable name is reserved.'); + otherwise + if isfield(Obj,Name) + Obj=rmfield(Obj,Name); + if isfield(Obj.API.Dimensions,Name) + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,Name); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..5773030f605cdbd2595fdf0635ccd146f2f66dd5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m @@ -0,0 +1,96 @@ +function [Obj] = SOFAsave(filename,Obj,varargin) +%SOFASAVE +% [Obj] = SOFAsave(filename,Obj,Compression) creates a new SOFA file and +% writes an entire data set to it. +% +% filename specifies the name of the SOFA file to which the data is written. +% Obj is a struct containing the data and meta +% data to be written to the SOFA file (see below for exact format). +% Compression is an optional numeric value between 0 and 9 specifying the +% amount of compression to be applied to the data when writing to the netCDF file. +% 0 is no compression and 9 is the most compression. +% +% The existence of mandatory variables will be checked. The dimensions +% will be updated. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc and header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAsave +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Def = SOFAdefinitions; + +%% check file name +filename=SOFAcheckFilename(filename); + +%% Remove private data +if isfield(Obj,'PRIVATE'), Obj=rmfield(Obj,'PRIVATE'); end + +%% Check convention: mandatory variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + +varNames = fieldnames(ObjCheck); +for ii=1:size(varNames,1); + if ~isfield(Obj,varNames{ii}) + error(['Mandatory variable/attribute not existing: ' varNames{ii}]); + end +end + +%% Get & set dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Check convention: read-only variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'r'); +varNames = fieldnames(ObjCheck); + +for ii=1:size(varNames,1); + if ischar(Obj.(varNames{ii})) + if ~strcmp(Obj.(varNames{ii}), ObjCheck.(varNames{ii})) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset from ' Obj.(varNames{ii}) ' to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + else + if Obj.(varNames{ii}) ~= ObjCheck.(varNames{ii}) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset from ' Obj.(varNames{ii}) ' to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + end +end + +%% check attributes (syntax, 1-dimensional string) +varNames = fieldnames(Obj); +for ii=1:size(varNames,1); + + if size(strfind(varNames{ii},'_'),2) == 1 + if ~ischar(Obj.(varNames{ii})) + error(['Attribute not a valid string: ' varNames{ii} ' = ' num2str(Obj.(varNames{ii}))]); + end + elseif size(strfind(varNames{ii},'_'),2) > 1 + error(['Attribute not valid (only one underscore "_" is allowed in attribute name): ' varNames{ii}]); + end + +end + +%% check varargin (compression) +if ~isempty(varargin) && isnumeric(varargin{1}) + if isscalar(varargin{1}) && varargin{1}>=0 && varargin{1}<=9 + Compression = varargin{1}; + else + error('Error: Compression must be a numeric scalar value between 0 and 9.'); + end +else + Compression = 1; % default +end + +%% Set/modify time information +Obj.GLOBAL_DateModified=datestr(now,Def.dateFormat); +if isempty(Obj.GLOBAL_DateCreated), Obj.GLOBAL_DateCreated=Obj.GLOBAL_DateModified; end + +%% Save file +NETCDFsave(filename,Obj,Compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..f4d978d1a0b0d4cb7721b2bf3fa8137e10f13d0e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m @@ -0,0 +1,112 @@ +function [out, azi, ele, idx] = SOFAspat(in,Obj,azi,ele) +% SOFAspat +% [out, azi, ele, idx] = SOFAspat(in, Obj, azi, ele) spatializes the sound IN using +% the HRTFs from OBJ according to the trajectory given in AZI and ELE. +% Input: +% in: vector with the sound +% Obj: SOFA object containing the HRTFs +% azi, ele: vectors with the trajectory (in degrees) independent for +% azimuth and elevation +% +% Output: +% out: binaural signal +% azi, ele: azimuth and elevation of the actual trajectory (degrees) +% idx: index of the filters (corresponds to AZI and ELE) +% +% This is an example of how to use SOFA. +% + +% #Author: Piotr Majdak (2013) +% #Author: Robert Baumgartner: adaptions (2016) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define required parameters +hop=0.5; % the hop size for the time-variant filtering (in fraction of the filter length) + +%% Initial checks +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + error('HRTFs must be saved in the SOFA conventions SimpleFreeFieldHRIR'); +end +if min(azi)<0, % Check for the required coordinate system + Obj.SourcePosition(:,1)=sph2nav(Obj.SourcePosition(:,1)); % if negative azimuths are required, swith to -90/+90 system +end +N=Obj.API.N; + +%% resize the input signal to be integer multiple of HRIR +L=length(in); +in=[in; zeros(N-mod(L,N),1)]; +L=length(in); % correct length of the input signal +S=L/N/hop; % number of segments to filter + +%% Resample the trajectory +if length(azi)>1, + azi= interp1(0:1/(length(azi)-1):1,azi,0:1/(S-1):1); +else + azi=repmat(azi,1,S); +end; +if length(ele)>1, + ele= interp1(0:1/(length(ele)-1):1,ele,0:1/(S-1):1); +else + ele=repmat(ele,1,S); +end; + +%% create a 2D-grid with nearest positions of the moving source +idx=zeros(S,1); +[target.x,target.y,target.z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(1,S)); +[pos.x,pos.y,pos.z] = sph2cart(deg2rad(Obj.SourcePosition(:,1)),... + deg2rad(Obj.SourcePosition(:,2)),Obj.SourcePosition(:,3)); +for ii=1:S % find nearest point on grid (LSP) + dist = (pos.x-target.x(ii)).^2 + (pos.y-target.y(ii)).^2 + (pos.z-target.z(ii)).^2; + [~,idx(ii)]=min(dist); +end + +%% normalize HRTFs to the frontal, eye-level position +% ii=find(Obj.SourcePosition(:,1)==0 & Obj.SourcePosition(:,2)==0); % search for position 0�/0� +% if isempty(ii) +% peak=max([sqrt(sum(Obj.Data.IR(:,1,:).*Obj.Data.IR(:,1,:))) sqrt(sum(Obj.Data.IR(:,2,:).*Obj.Data.IR(:,2,:)))]); % not found - normalize to IR with most energy +% else +% peak=([sqrt(sum(Obj.Data.IR(ii,1,:).*Obj.Data.IR(ii,1,:))) sqrt(sum(Obj.Data.IR(ii,2,:).*Obj.Data.IR(ii,2,:)))]); % found - normalize to this position +% end + +%% Spatialize +out=zeros(L+N/hop,2); +window=hanning(N); +ii=0; +jj=1; +iiend=L-N; +while ii<iiend + segT=in(ii+1:ii+N).*window; % segment in time domain + segF=fft(segT,2*N); % segment in frequency domain with zero padding + %----------- + segFO(:,1)=squeeze(fft(Obj.Data.IR(idx(jj),1,:),2*N)).*segF; + segFO(:,2)=squeeze(fft(Obj.Data.IR(idx(jj),2,:),2*N)).*segF; + %----------- + segTO=real(ifft(segFO)); % back to the time domain + out(ii+1:ii+2*N,:)=out(ii+1:ii+2*N,:)+segTO; % overlap and add + ii=ii+N*hop; + jj=jj+1; +end + +%% Normalize +% out(:,1)=out(:,1)/peak(1); +% out(:,2)=out(:,2)/peak(2); + +%% Output +% actually used angles +azi = Obj.SourcePosition(idx,1); +ele = Obj.SourcePosition(idx,2); +% upsampled for each sample +idup = floor(1:1/(N*hop):S+1-1/(N*hop)); +azi = azi(idup); +ele = ele(idup); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m new file mode 100644 index 0000000000000000000000000000000000000000..01a69bfdc557f701583d55931e79823eaec43f1f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m @@ -0,0 +1,117 @@ +function SOFAstart(flags) +% SOFAstart +% +% SOFAstart adds all needed pathes and checks if we need the Matlab or Octave +% version of the API +% +% SOFAstart(0) or SOFAstart('silent') will suppress any message during the start. +% SOFAstart ('short') will show a short header only during the start. +% SOFAstart ('full') will show all information, including all compiled +% conventions & versions. +% +% SOFAstart checks if SOFA has been started within the MATLAB session. If +% it is the case, SOFAstart skips all the initialization. If the initialization +% is required, SOFAstart('restart') performs the initialization in any case. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: 'full' flag added, changed order of display output messages (11.11.2021) +% #Author: Michael Mihocic: bug fixed when adding paths (29.11.2021) +% +% SOFA Toolbox - function SOFAstart +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Input parameters +verbose = 2; +restart = 0; +if nargin>0 + if strcmpi(flags,'silent'), verbose=0; end + if strcmpi(flags,'short'), verbose=1; end + if strcmpi(flags,'full'), verbose=3; end + if isnumeric(flags), if flags==0, verbose=0; end; end + if strcmpi(flags,'restart'), restart=1; end +end + +%% do not start when already started but not forced to restart +persistent started +if ~isempty(started) && ~restart + return; +end +started=1; +%% Check required support +if exist('OCTAVE_VERSION','builtin') + % We're in Octave + if compare_versions(OCTAVE_VERSION,'3.6.0','<=') % check if the octave version is high enough + error('You need Octave >=3.6.0 to work with SOFA.'); + end + pkg load netcdf + if ~which('test_netcdf') % check if octcdf is installed + error('You have to install the netcdf package in Octave to work with SOFA.'); + end +else + % We're in Matlab + if verLessThan('matlab','8') + warning('SOFA:start','SOFA for Matlab version <= 8 (2012b) not tested. Use on your risk.'); + end +end + + +%% Add Paths +% Get the basepath as the directory this function resides in. +% The 'which' solution below is more portable than 'mfilename' +% becase old versions of Matlab does not have "mfilename('fullpath')" +basepath=which('SOFAstart'); +basepath=basepath(1:end-12); % Kill the function name from the path. +f=filesep; + +% Add the base path and the needed sub-directories +% (basepath is added in case user navigated to this folder and changes dir) +if exist('addpath','file') || exist('addpath','builtin') % in Matlab it is a 'file'; in Octave it is a 'built-in' function + addpath(basepath,[basepath f 'helpers'],[basepath f 'coordinates'],[basepath f 'converters'],[basepath f 'demos'],[basepath f 'netcdf']); +else % in case "addpath" command is not available - can this ever be the case??? + path([basepath f 'helpers'],path); + path([basepath f 'coordinates'],path); + path([basepath f 'converters'],path); + path([basepath f 'demos'],path); + path([basepath f 'netcdf'],path); + path(path,basepath); +end + + +%% Provide SOFA conventions +dispOutput = SOFAcompileConventions; +convs = SOFAgetConventions; + +%% Display general informations + +if verbose + disp(['SOFA Matlab/Octave API, version ' SOFAgetVersion '. Copyright 2013-2022 Acoustics Research Institute (piotr@majdak.com).']); + if verbose >= 3 + disp(dispOutput); + end + if verbose >= 2 + disp(['This API implements SOFA version ' SOFAgetVersion('SOFA') '.']); + text=['Available SOFA Conventions: ' convs{1}]; + for ii=2:length(convs) + text=[text ', ' convs{ii}]; + end + disp(text); + disp(['SOFAdbPath (local HRTF database): ' SOFAdbPath('reset') ]); + disp(['SOFAdbURL (internet repository): ' SOFAdbURL('reset')]); + end +end + + + +% FIXME: I would check only if the URL is available in the function where it is +% needed. At the start it takes to long. Octaves urlread didn't know the TimeOut +% parameter. +%[~,stat]=urlread(SOFAdbURL); +%if ~stat, disp(' --> could not connect'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m new file mode 100644 index 0000000000000000000000000000000000000000..5dbafdffb3fac9fa18c772584ce1d83f12090628 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m @@ -0,0 +1,181 @@ +function Obj = SOFAupdateDimensions(Obj,varargin) +%SOFAupdateDimensions +% Obj = SOFAupdateDimensions(Obj, varargin) updates the dimensions in the SOFA +% structure +% +% Obj is a struct containing the data and meta. +% The dimension sizes are created as .API.X and updated corresponding to the +% conventions +% flag is 'nodata', 'all', or 'verbose'; default is 'all' +% set 'verbose' to 1 to obtain detailed information on the check. + +% #Author: Piotr Majdak +% #Author: Piotr Majdak: String support added (09.08.2014) +% #Author: Piotr Majdak: Verbose mode added (10.10.2020) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupdateDimensions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.keyvals.Index=[]; +definput.keyvals.verbose=0; +definput.flags.type={'data','nodata'}; +[flags,kv]=SOFAarghelper({'Index'},definput,varargin); +v=kv.verbose; + +%% Get conventions with allowed dimensions +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +if v, disp(['SOFA Convention: ' Obj.GLOBAL_SOFAConventions]); end + +%% Add dimensions if required +dims=fieldnames(SOFAdefinitions('dimensions')); +for ii=1:size(dims,1) + if ~isfield(Obj.API,dims{ii}), Obj.API.(dims{ii})=0; end +end + +%% Update dimension sizes from the variables having dominant dimensions sizes + % fix dimension sizes +Obj.API.I=1; +Obj.API.C=3; + % check all metadata variables for dominant dimension sizes +dims='renm'; +f=fieldnames(rmfield(OC.API.Dimensions,'Data')); +for ii=1:length(dims) + for jj=1:length(f) + dim=strfind(OC.API.Dimensions.(f{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(f{jj}),dim(1)); + if (v), disp([upper(dims(ii)) ' set to ' num2str(size(Obj.(f{jj}),dim(1))) ' that is the #' num2str(dim(1)) ' dimension of ' f{jj}]); end + break; + end + end +end +% check all data variables +if flags.do_data + fd=fieldnames(OC.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fd) + dim=strfind(OC.API.Dimensions.Data.(fd{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fd{jj}),dim(1)); + if (v), disp([upper(dims(ii)) ' set to ' num2str(size(Obj.Data.(fd{jj}),dim(1))) ' that is the #' num2str(dim(1)) ' dimension of Data.' fd{jj}]); end + break; + end + end + end +end + +%% Update the dimensions of metadata variables +Smax=0; +X=rmfield(Obj,{'Data','API'}); +if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end +Xf=fieldnames(X); +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions, Xf{ii}), % is a known variable + dim=OC.API.Dimensions.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.(Xf{ii})=dim; + if v, disp([Xf{ii} ': convention variable, used dimension: ' dim]); end; + end + else % is a user-defined variable + if ~isfield(Obj.API.Dimensions,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without dimension provided in API.Dimensions.']); + else + dim=Obj.API.Dimensions.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension does not match.']); + else + if v, disp([Xf{ii} ': user-defined variable, used dimension: ' dim]); end; + end + end + end + Smax=max(Smax,S); + end +end +%% Update the dimensions of data variables +if flags.do_data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions.Data, Xf{ii}), % is a known variable + dim=OC.API.Dimensions.Data.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.Data.(Xf{ii})=dim; + if v, disp(['Data.' Xf{ii} ': convention variable, used dimension: ' dim]); end; + end + Smax=max(Smax,S); + else + if ~isfield(Obj.API.Dimensions.Data,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without a dimension.']); + else + dim=Obj.API.Dimensions.Data.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension does not match.']); + else + if v, disp(['Data.' Xf{ii} ': user-defined variable, used dimension: ' dim]); end; + end + end + end + end + end +end +%% Update the size of the longest string +if Smax>0, + Obj.API.S=Smax; + if v, disp(['S set to ' num2str(Obj.API.S)]); end +else + if v, disp('S unused (set to 0)'); end +end + +%% Return the size of x. If x is a cell, return the size of the strings in x. +function s=sizecell(x,dim) +if iscell(x) + s=size(char(x)); + if size(x,1)~=s(1) s=[size(x) s(2)]; end % multidim cellarays: s = [celldim1, celldim2, ... , celldimN, stringdim] +else + s=size(x); +end + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.(f)),upper(str)); + +%% dims is a cell array with allowed dimensions. +% S is the size of the string dimension. S=0 when S does not exist +% dimA is a vector with the actual dimensions. +% dim is a string with the matching dimension +function [dim,S]=checkdim(Obj,dims,dimA) +dim=[]; S=0; +for jj=1:length(dims) + dimS=dims{jj}; + if length(dimS)==1, dimS=[dimS 'I']; end; % 1D required, but Matlab is always 2D at least. + dimR=getdim(Obj.API,dimS); + if length(dimA)==length(dimR), % the same size? + if ~isempty(strfind(dimS,'S')) + Sidx=strfind(dimS,'S'); + S=max(S,dimA(Sidx)); + dimR(Sidx)=dimA(Sidx); % string dim are always correct + end + if dimA==dimR, dim=upper(dims{jj}); break; end; % found! + elseif length(dimA)<length(dimR) % extend the size? + if [dimA ones(1,length(dimR)-length(dimA))]==dimR, dim=upper(dims{jj}); break; end; % found! + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..e1acb20158d187b75073a274e0486ee86444ab10 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m @@ -0,0 +1,174 @@ +function [Obj,modified] = SOFAupgradeConventions(Obj) +%SOFAcompatibility +% [Obj,modified] = SOFAupgradeConventions(Obj) upgrades the Obj to the next higher +% version if required. MODIFIED is 1 when an upgrade was required. +% In order to obtain the most recent version, SOFAupgradeConventions +% should be processed recursively until MODIFIED is 0. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupgradeConventions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +modified=0; + +%% Upgrade specific to a SOFA version + +switch Obj.GLOBAL_Version, + case '0.3' + modified=1; + % in SOFA 0.3, only SimpleFreeFieldHRIR 0.1 was supported. + % Updating SimpleFreeFieldHRIR 0.1 to 0.2 + Obj.GLOBAL_Version='0.4'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + Obj.GLOBAL_TimeCreated=Obj.GLOBAL_DatabaseTimeCreated; + Obj.GLOBAL_TimeModified=Obj.GLOBAL_DatabaseTimeModified; + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.3'); + % remove dimensional variables and not used variables/attributes + dims={'I','R','E','N','M','C','Q','SourceView',... + 'SourceUp','GLOBAL_DatabaseTimeCreated','GLOBAL_DatabaseTimeModified'}; + f=fieldnames(Obj); + for ii=1:length(dims) + for jj=1:length(f) + if strcmp(f{jj},dims{ii}), + Obj=rmfield(Obj,f{jj}); % remove variable or attribute + if isempty(strfind(f{jj},'_')), + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,f{jj}); % remove dimension + end + elseif strcmp(f{jj}(1:min(length(dims{ii})+1,length(f{jj}))),[dims{ii} '_']) + Obj=rmfield(Obj,f{jj}); % remove attributes of that variable + end + end + end + warning('SOFA:upgrade','SOFA 0.3 upgraded to 0.4. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.4' + % in SOFA 0.4, only SimpleFreeFieldHRIR might need upgrade + if strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + switch Obj.GLOBAL_SOFAConventionsVersion + case '0.2' + % Upgrade from SimpleFreeFieldHRIR 0.2 to 0.3 + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SimpleFreeFieldHRIR 0.2'); + % Create temp SourcePosition + azi=bsxfun(@times,Obj.ListenerRotation(:,1),ones(size(Obj.ListenerPosition,1),1)); + ele=bsxfun(@times,Obj.ListenerRotation(:,2),ones(size(Obj.ListenerPosition,1),1)); + r=bsxfun(@times,Obj.ListenerPosition(:,1),ones(size(Obj.ListenerRotation,1),1)); + % Copy ListenerPosition + Obj.ListenerPosition=Obj.SourcePosition; + % Overwrite SourcePosition + Obj.SourcePosition=[azi ele r]; + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degree, degree, meter'; + % Mirror the ListenerView and correct ListenerUp + Obj.ListenerView=-Obj.ListenerView; + Obj.ListenerUp=[0 0 1]; + % Remove irrelevant fields + if isfield(Obj,'SourceView'); Obj=rmfield(Obj,'SourceView'); end + if isfield(Obj,'SourceView_Type'); Obj=rmfield(Obj,'SourceView_Type'); end + if isfield(Obj,'SourceView_Units'); Obj=rmfield(Obj,'SourceView_Units'); end + if isfield(Obj,'SourceUp'); Obj=rmfield(Obj,'SourceUp'); end + if isfield(Obj,'SourceUp_Type'); Obj=rmfield(Obj,'SourceUp_Type'); end + if isfield(Obj,'SourceUp_Units'); Obj=rmfield(Obj,'SourceUp_Units'); end + Obj=rmfield(Obj,'ListenerRotation'); + Obj=rmfield(Obj,'ListenerRotation_Type'); + Obj=rmfield(Obj,'ListenerRotation_Units'); + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,'ListenerRotation'); + Obj.GLOBAL_SOFAConventionsVersion='0.3'; + end + end + modified=1; + Obj.GLOBAL_Version='0.5'; + warning('SOFA:upgrade','SOFA 0.4 upgraded to 0.5. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.5' + % Upgrade from 0.5 to 0.6 + Obj.GLOBAL_DateCreated=Obj.GLOBAL_TimeCreated; + Obj=rmfield(Obj,'GLOBAL_TimeCreated'); + Obj.GLOBAL_DateModified=Obj.GLOBAL_TimeModified; + Obj=rmfield(Obj,'GLOBAL_TimeModified'); + Obj.GLOBAL_Origin=Obj.GLOBAL_Source; + Obj=rmfield(Obj,'GLOBAL_Source'); + if isfield(Obj,'ListenerView') && ~isfield(Obj,'ListenerView_Type') + Obj.ListenerView_Type = 'cartesian'; + Obj.ListenerView_Units = 'meter'; + end + if isfield(Obj,'ReceiverView') && ~isfield(Obj,'ReceiverView_Type') + Obj.ReceiverView_Type = 'cartesian'; + Obj.ReceiverView_Units = 'meter'; + end + if isfield(Obj,'GLOBAL_SubjectID'), + Obj.GLOBAL_ListenerShortName=Obj.GLOBAL_SubjectID; % rename SubjectID to ListenerShortName + Obj=rmfield(Obj,'GLOBAL_SubjectID'); + end + switch Obj.GLOBAL_SOFAConventions + case {'SimpleFreeFieldHRIR', 'SimpleFreeFieldTF'} + Obj.GLOBAL_SOFAConventionsVersion='0.4'; + case {'GeneralFIR', 'GeneralTF', 'SingleRoomDRIR'} + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + end + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.5'); + Obj.GLOBAL_Version='0.6'; + modified=1; + warning('SOFA:upgrade','SOFA 0.5 upgraded to 0.6. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.6' + X=SOFAgetConventions(Obj.GLOBAL_SOFAConventions); + if ~isempty(X), + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.6'); + Obj.GLOBAL_Version='1.0'; + Obj.GLOBAL_SOFAConventionsVersion = X.GLOBAL_SOFAConventionsVersion; + % replace aliases by correct unit names + U=SOFAdefinitions('units'); + Uf=fieldnames(U); + f=fieldnames(Obj); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.(f{jj})=regexprep(Obj.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + f=fieldnames(Obj.Data); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.Data.(f{jj})=regexprep(Obj.Data.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + modified=1; + warning('SOFA:upgrade','SOFA 0.6 upgraded to 1.0. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + else + warning('SOFA:upgrade','Unknown conventions'); + end +end + +%% Upgrade specific to conventions +if ~modified + switch Obj.GLOBAL_SOFAConventions + case 'MultiSpeakerBRIR' + if strcmp(Obj.GLOBAL_SOFAConventionsVersion,'0.1'); + % upgrade to 0.2 + Obj.GLOBAL_DataType='FIRE'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + %Obj.Data.Delay = + if strcmp(Obj.API.Dimensions.Data.Delay,'IR') + Obj.API.Dimensions.Data.Delay='IRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + if strcmp(Obj.API.Dimensions.Data.Delay,'MR') + Obj.API.Dimensions.Data.Delay='MRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + modified=1; + warning('SOFA:upgrade','Conventions MultiSpeakerBRIR 0.1 upgraded to 0.2. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..fa39ddb4772064bfa0d9f27259c256aff14605f9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv @@ -0,0 +1,58 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldDirectivityTF rm attribute This conventions stores directivities of acoustic sources (instruments, loudspeakers, singers, talkers, etc) in the frequency domain for multiple musical notes in free field. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:RoomType free field m attribute The room information can be arbitrary, but the spatial setup assumes free field. +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment m attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data +GLOBAL:Musician attribute Narrative description of the musician such as position, behavior, or personal data if not data-protected, e.g., 'Christiane Schmidt sitting on the chair', or 'artificial excitation by R2D2'. +GLOBAL:Description attribute Narrative description of a measurement. For musical instruments/singers, the note (C1, D1, etc) or the dynamic (pp., ff., etc), or the string played, the playing style (pizzicato, legato, etc.), or the type of excitation (e.g., hit location of a cymbal). For loudspeakers, the system and driver units. +GLOBAL:SourceType m attribute Narrative description of the acoustic source, e.g., 'Violin', 'Female singer', or '2-way loudspeaker' +GLOBAL:SourceManufacturer m attribute Narrative description of the manufacturer of the source, e.g., 'Stradivari, Lady Blunt, 1721' or 'LoudspeakerCompany' +ListenerPosition [0 0 0] m IC, MC double Position of the microphone array during the measurements. +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double Orientation of the microphone array +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +ListenerUp [0 0 1] m IC, MC double Up vector of the microphone array +ReceiverPosition [0 0 1] m IC, RC, RCM double Positions of the microphones during the measurements (relative to the Listener) +ReceiverPosition:Type spherical m attribute +ReceiverPosition:Units degree, degree, metre m attribute +SourcePosition [0 0 0] m IC, MC double Position of the acoustic source (instrument) +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourcePosition:Reference m attribute Narrative description of the spatial reference of the source position, e.g., for the trumpet, 'The bell'. Mandatory in order to provide a reference across different instruments +SourceView [1 0 0] m IC, MC double Orientation of the acoustic source (instrument) +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +SourceView:Reference m attribute Narrative description of the spatial reference of the source view, e.g., for the trumpet, 'Viewing direction of the bell'. Mandatory in order to provide a reference across different instruments +SourceUp [0 0 1] m IC, MC double Up vector of the acoustic source (instrument) +SourceUp:Reference m attribute Narrative description of the spatial reference of the source up, e.g., for the trumpet, 'Along the keys, keys up'. Mandatory in order to provide a reference across different instruments +EmitterPosition [0 0 0] m IC, MC double A more detailed structure of the Source. In a simple settings, a single Emitter is considered that is collocated with the source. +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterDescription {''} IS, MS string A more detailed structure of the source. In a simple setting, a single Emitter is considered that is collocated with the source. In a more complicated setting, this may be the strings of a violin or the units of a loudspeaker. +MIDINote 0 I, M double Defines the note played by the source during the measurement. The note is specified a MIDI note by the [https://www.midi.org/specifications-old/item/the-midi-1-0-specification MIDI specifications, version 1.0]. Not mandatory, but recommended for tonal instruments. +Description {''} MS string This variable is used when the description varies with M. +SourceTuningFrequency 440 I, M double Frequency (in hertz) to which a musical instrument is tuned to corresponding to the note A4 (MIDINote=69). Recommended for tonal instruments. +Data.Real 0 m MRN double Real part of the complex spectrum. The default value 0 indicates that all data fields are initialized with zero values. +Data.Imag 0 m MRN double Imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Units used for N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.1.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.1.csv new file mode 100644 index 0000000000000000000000000000000000000000..08f0f7cf7721f6b734155d8bf122b88a615bf567 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.1.csv @@ -0,0 +1,59 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldDirectivityTF rm attribute This conventions stores directivities of acoustic sources (instruments, loudspeakers, singers, talkers, etc) in the frequency domain for multiple musical notes in free field. +GLOBAL:SOFAConventionsVersion 1.1 rm attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:RoomType free field m attribute The room information can be arbitrary, but the spatial setup assumes free field. +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data +GLOBAL:Musician attribute Narrative description of the musician such as position, behavior, or personal data if not data-protected, e.g., 'Christiane Schmidt sitting on the chair', or 'artificial excitation by R2D2'. +GLOBAL:Description attribute Narrative description of a measurement. For musical instruments/singers, the note (C1, D1, etc) or the dynamic (pp., ff., etc), or the string played, the playing style (pizzicato, legato, etc.), or the type of excitation (e.g., hit location of a cymbal). For loudspeakers, the system and driver units. +GLOBAL:SourceType m attribute Narrative description of the acoustic source, e.g., 'Violin', 'Female singer', or '2-way loudspeaker' +GLOBAL:SourceManufacturer m attribute Narrative description of the manufacturer of the source, e.g., 'Stradivari, Lady Blunt, 1721' or 'LoudspeakerCompany' +ListenerPosition [0 0 0] m IC, MC double Position of the microphone array during the measurements. +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double Orientation of the microphone array +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +ListenerUp [0 0 1] m IC, MC double Up vector of the microphone array +ReceiverPosition [0 0 0] m IC, RC, RCM double Positions of the microphones during the measurements (relative to the Listener) +ReceiverPosition:Type spherical m attribute Type of the coordinate system used. +ReceiverPosition:Units degree, degree, metre m attribute Units of the coordinates. +SourcePosition [0 0 0] m IC, MC double Position of the acoustic source (instrument) +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourcePosition:Reference m attribute Narrative description of the spatial reference of the source position, e.g., ‘The bell’ for a trumpet or ‘On the front plate between the low- and mid/high-frequency unit’ for a loudspeaker. Mandatory in order to provide a reference across different sources. +SourceView [1 0 0] m IC, MC double View vector for the orientation. +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +SourceView:Reference m attribute Narrative description of the spatial reference of the source view, e.g., ‘Viewing direction of the bell’ for a trumpet or 'Perpendicular to the front plate` for a loudspeaker. Mandatory in order to provide a reference across different sources. +SourceUp [0 0 1] m IC, MC double Up vector of the acoustic source (instrument) +SourceUp:Reference m attribute Narrative description of the spatial reference of the source up, e.g., ‘Along the keys, keys up’ for a trumpet or ‘Perpendicular to the top plate’ for a loudspeaker. Mandatory in order to provide a reference across different sources. +EmitterPosition [0 0 0] m EC, ECM double Position. In a simple settings, a single emitter is considered that is collocated with the source. +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterDescription {''} IS, MS string A more detailed structure of the source. In a simple setting, a single Emitter is considered that is collocated with the source. In a more complicated setting, this may be the strings of a violin or the units of a loudspeaker. +GLOBAL:EmitterDescriptions MS string A more detailed description of the Emitters. For example, this may be the strings of a violin or the units of a loudspeaker. +MIDINote 0 I, M double Defines the note played by the source during the measurement. The note is specified a MIDI note by the [https://www.midi.org/specifications-old/item/the-midi-1-0-specification MIDI specifications, version 1.0]. Not mandatory, but recommended for tonal instruments. +Description {''} MS string This variable is used when the description varies with M. +SourceTuningFrequency 440 I, M double Frequency (in hertz) to which a musical instrument is tuned to corresponding to the note A4 (MIDINote=69). Recommended for tonal instruments. +Data.Real 0 m MRN double Real part of the complex spectrum. The default value 0 indicates that all data fields are initialized with zero values. +Data.Imag 0 m MRN double Imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency attribute Optional +N:Units hertz m attribute Units used for N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..5321640181eb021ff0fc9b76d81474f30ba7477d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldHRIR rm attribute An extension of SimpleFreeFieldHRIR in order to consider more complex data sets described in spatially continuous representation. Each HRTF direction corresponds to an emitter, and a consistent measurement for a single listener and all directions is described by a set of the emitter positions surrounding the listener. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR-E rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute Short name of the listener (as for example the subject ID). +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Source position is assumed to be the ListenerPosition in order to reflect Emitters surrounding the Listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double Radius in 'spherical harmonics', Position in 'cartesian' and 'spherical' +EmitterPosition:Type spherical harmonics m attribute Can be 'spherical harmonics', 'cartesian', or 'spherical' +EmitterPosition:Units degree, degree, metre m attribute +GLOBAL:DatabaseName m attribute Name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.IR [0 0] m MRNE double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IRI, MRI, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..d7481c9ebccaa6531c7fa205b00f08b2f4d52859 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldHRTF rm attribute This conventions is for HRTFs created under conditions where room information is irrelevant and stored as SH coefficients +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF-E rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Source position is assumed to be the ListenerPosition in order to reflect Emitters surrounding the Listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double Radius in 'spherical harmonics', Position in 'cartesian' and 'spherical' +EmitterPosition:Type spherical harmonics m attribute Can be 'spherical harmonics', 'cartesian', or 'spherical' +EmitterPosition:Units degree, degree, metre m attribute +GLOBAL:DatabaseName m attribute Name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.Real [0 0] m MRNE double +Data.Imag [0 0] m MRNE double +N 0 m N double +N:LongName frequency attribute +N:Units Hertz m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..0ea2192b243e79b7337c3368cea54fe6b875f541 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR-E rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR-E rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, EC, ECM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mrne double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..c767c77a815dd871c45098f2e851e17c424cebcf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIRE rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mREn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..a3d46ef46e288224905e221d7f5381c0f6c431d2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mRn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..9845f4b14ded04145b7479f021a2c7a88fc52db2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..72f5cf8226401f1fc6057d99839241cc91bee519 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralSOS rm attribute This conventions follows GeneralFIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0], [3 1 2]); m mrn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I, M double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv new file mode 100644 index 0000000000000000000000000000000000000000..3b2668520b8202463d5ba28c21408ddb797f0415 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralString rm attribute Conventions for testing the string support +GLOBAL:SOFAConventionsVersion 0.2 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType String rm attribute We store strings here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +String2 {'' ''} m MRS string +String2:Description 2-D string m attribute +String2:Units latin1 m attribute +Data.String1 {''} m MS string +Data.String1:Description 1-D string m attribute +Data.String1:Units latin1 m attribute +Data.String2 {'' ''} m MRS string +Data.String2:Description 2-D string m attribute +Data.String2:Units latin1 m attribute +Data.Double [0 0] m mRn double +Data.Double:Units double m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..bcd48c849b46ee48330af12bd2ba5f6ae52bf09d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralTF-E rm attribute This conventions stores TFs depending in the Emiiter for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralTF +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF-E rm attribute We store frequency-dependent data depending on the emitter here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, EC, ECM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mrne double The real part of the complex spectrum +Data.Imag 0 m MRNE double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..3a14a5de1231813d3a5bab18f38ebb029084e067 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralTF rm attribute This conventions stores TFs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralFIR. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mRn double The real part of the complex spectrum +Data.Imag 0 m MRN double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..ddb04c75fd6aecebf453782881b1e6d3194eaa02 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralTF rm attribute This conventions stores TFs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralFIR. +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eC, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mrn double The real part of the complex spectrum +Data.Imag 0 m MRN double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..73696de08abd826f5eb3da8d460aef2845c1618f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv @@ -0,0 +1,61 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions General rm attribute This conventions is for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR m attribute The datatype can be arbitrary +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] IC, MC double +ListenerUp [0 0 1] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] IC, MC double +SourceUp [0 0 1] IC, MC double +SourceView:Type cartesian attribute +SourceView:Units metre attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmiiterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv new file mode 100644 index 0000000000000000000000000000000000000000..bb45db38ab7773c59b5361ca94cdb43d1b8e5122 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv @@ -0,0 +1,48 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions MultiSpeakerBRIR rm attribute This convention is for BRIRs recorded in reverberant conditions from multiple loudspeaker sources at a number of listener orientations. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:RoomDescription attribute narrative description of the room +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +EmitterUp [0 0 1] ECI, ECM double When EmitterUp provided, EmitterView must be provided as well +EmitterView [1 0 0] ECI, ECM double When EmitterView provided, EmitterUp must be provided as well +EmitterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR [1 1] m mREn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IRE, MRE double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..3307cfcbbcc50ae300ca91e98b73cd44e1a9a8d4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv @@ -0,0 +1,47 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRIR rm attribute This convention set is for HRIRs recorded under free-field conditions or other IRs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double +SourceUp [0 0 1] IC, MC double +SourceView [1 0 0] IC, MC double +SourceView:Type cartesian attribute +SourceView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..9aecc490b9896ddbc6cab3a90a8074a36721e031 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRSOS rm attribute This convention set follows SimpleFreeFieldHRIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0; 0 0 0 1 0 0], [3 1 2]); m mRn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I, M double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..327c97f1a3379634d099054873a9ca05fa79c9d7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRTF rm attribute This conventions is for HRTFs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.Real [0 0] m mRn double +Data.Imag [0 0] m MRN double +N 0 m N double +N:LongName frequency attribute +N:Units hertz m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..f576df1d3caaf1fa072d279d150326ea5798ac27 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldSOS rm attribute This convention set follows SimpleFreeFieldHRIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0; 0 0 0 1 0 0], [3 1 2]); m mRn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..a19745727c4d794d46059ed58e060ed9e3919afc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv @@ -0,0 +1,51 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleHeadphoneIR rm attribute Conventions for IRs with a 1-to-1 correspondence between emitter and receiver. The main application for this convention is to store headphone IRs recorded for each emitter and each ear. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR rm attribute We will store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute Room type is not relevant here +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Default: Headphones are located at the position of the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0.09 0; 0 -0.09 0] m eCI, eCM double Default: Reflects the correspondence of each emitter to each receiver +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double +GLOBAL:DatabaseName m attribute Correspondence to a database +GLOBAL:ListenerShortName m attribute Correspondence to a subject from the database +GLOBAL:ListenerDescription m attribute Narrative description of the listener (or mannequin) +GLOBAL:SourceDescription m attribute Narrative description of the headphones +GLOBAL:SourceManufacturer m attribute Name of the headphones manufacturer +SourceManufacturer {''} MS string Optional M-dependent version of the attribute SourceManufucturer +GLOBAL:SourceModel m attribute Name of the headphone model. Must uniquely describe the headphones of the manufacturer +SourceModel {''} MS string Optional M-dependent version of the attribute SourceModel +GLOBAL:SourceURI m attribute URI of the headphone specifications +GLOBAL:ReceiverDescription m attribute Narrative description of the microphones +ReceiverDescriptions {''} MS string R-dependent version of the attribute ReceiverDescription +GLOBAL:EmitterDescription m attribute Narrative description of the headphone drivers +EmitterDescriptions {''} MS string E-dependent version of the attribute EmitterDescription +MeasurementDate 0 M double Optional M-dependent date and time of the measurement diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv new file mode 100644 index 0000000000000000000000000000000000000000..0658a79a697550a8a25f646859395b24383df7a3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv @@ -0,0 +1,47 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SingleRoomDRIR rm attribute This convention stores arbitrary number of receivers while providing an information about the room. The main application is to store DRIRs for a single room. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute +GLOBAL:RoomDescription m attribute +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +SourceUp [0 0 1] m IC, MC double +SourceView [-1 0 0] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +Data.IR [0] m mrn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0] m IR, MR double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..7f83b04c5db8a3e21ee5474a5f3b96ccf39e6294 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv @@ -0,0 +1,77 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SingleRoomMIMOSRIR rm attribute Single-room multiple-input multiple-output spatial room impulse responses, depending on Emitters +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR-E rm attribute Shall be FIR-E +GLOBAL:RoomType shoebox m attribute Shall be 'shoebox' or 'dae' +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data. +GLOBAL:RoomShortName attribute Short name of the Room +GLOBAL:RoomDescription attribute Informal verbal description of the room +GLOBAL:RoomLocation attribute Location of the room +GLOBAL:RoomGeometry attribute URI to a file describing the room geometry. +RoomTemperature 0 I, M double Temperature during measurements +RoomTemperature:Units kelvin attribute Units of the room temperature +RoomVolume 0 I, M double Volume of the room +RoomVolume:Units cubic metre attribute Units of the room volume +RoomCornerA [0 0 0] IC, MC double +RoomCornerB [1 2 3] IC, MC double +RoomCorners 0 II double The value of this attribute is to be ignored. It only exist to for RoomCorners:Type and RoomCorners:Units +RoomCorners:Type cartesian attribute +RoomCorners:Units metre attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double +ListenerUp [0 0 1] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverDescriptions {''} RS string R-dependent version of the attribute ReceiverDescription +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type spherical m attribute Can be of any type enabling both spatially discrete and spatially continuous representations. +ReceiverPosition:Units degree, degree, metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] m IC, MC double +SourceUp [0 0 1] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterDescriptions {''} ES string E-dependent version of the attribute EmitterDescription +EmitterPosition [0 0 0] m IC, ECI, ECM double Can be of any type enabling both spatially discrete and spatially continuous representations. +EmitterPosition:Type spherical m attribute +EmitterPosition:Units degree, degree, metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmitterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR 0 m mrne double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRI, MRI, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..08abef00675f9c50d4aac3c0a552cfb67c2f1cbe --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv @@ -0,0 +1,77 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SingleRoomSRIR rm attribute For measuring SRIRs in a single room with a single excitation source (e.g., a loudspeaker) and a listener containing an arbitrary number of omnidirectional receivers (e.g., a microphone array). +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR rm attribute Shall be FIR +GLOBAL:RoomType shoebox m attribute Shall be 'shoebox' or 'dae' +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data. +GLOBAL:RoomShortName attribute Short name of the Room +GLOBAL:RoomDescription attribute Informal verbal description of the room +GLOBAL:RoomLocation attribute Location of the room +GLOBAL:RoomGeometry attribute URI to a file describing the room geometry. +RoomTemperature 0 I, M double Temperature during measurements +RoomTemperature:Units kelvin attribute Units of the room temperature +RoomVolume 0 I, M double Volume of the room +RoomVolume:Units cubic metre attribute Units of the room volume +RoomCornerA [0 0 0] IC, MC double +RoomCornerB [1 2 3] IC, MC double +RoomCorners 0 II double The value of this attribute is to be ignored. It only exist to for RoomCorners:Type and RoomCorners:Units +RoomCorners:Type cartesian attribute +RoomCorners:Units metre attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double +ListenerUp [0 0 1] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverDescriptions {''} RS string R-dependent version of the attribute ReceiverDescription +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type spherical m attribute Can be of any type enabling both spatially discrete and spatially continuous representations. +ReceiverPosition:Units degree, degree, metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] m IC, MC double +SourceUp [0 0 1] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterDescriptions {''} ES string E-dependent version of the attribute EmitterDescription +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type spherical m attribute Shall be 'cartesian' or 'spherical', restricting to spatially discrete emitters. +EmitterPosition:Units degree, degree, metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmitterView:Type cartesian attribute Shall be 'cartesian' or 'spherical', restricting to spatially discrete emitters. +EmitterView:Units metre attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..3d885d7c8b34b5aa62ded535f12efa619d8c6f97 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m @@ -0,0 +1,49 @@ +function Obj=SOFAconvertARI2SOFA(hM,meta,stimPar) +% OBJ=SOFAconvertARI2SOFA(hM,meta,stimPar) converts the HRTFs described in hM, meta, and +% stimPar (see ARI HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(hM,1); % hM is [N M R], data.IR must be [M R N] +Obj.Data.SamplingRate = stimPar.SamplingRate; + +%% Fill with attributes +if isfield(stimPar, 'SubjectID'), Obj.GLOBAL_ListenerShortName = stimPar.SubjectID; end +if isfield(stimPar,'Application') + if isfield(stimPar.Application,'Name'), Obj.GLOBAL_ApplicationName = stimPar.Application.Name; end + if isfield(stimPar.Application,'Version'), Obj.GLOBAL_ApplicationVersion = stimPar.Application.Version; end +end + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.2 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) zeros(size(hM,2),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) 1.2*ones(size(hM,2),1)]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with some additional data +Obj.GLOBAL_History='Converted from the ARI format'; +if size(meta.pos,2)>2, Obj=SOFAaddVariable(Obj,'MeasurementSourceAudioChannel','M',meta.pos(1:size(hM,2),3)); end +if isfield(meta,'lat'), Obj=SOFAaddVariable(Obj,'MeasurementAudioLatency','MR',meta.lat); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8e8eee834f3eecbf5cf0586460bce52910c01df4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m @@ -0,0 +1,83 @@ +function Obj = SOFAconvertBTDEI2SOFA(BTDEI) +% OBJ=SOFAconvertBTDEI2SOFA(BTDEI) converts the HRTFs described in BT-DEI +% to a SOFA object. +% +% BTDEI format is used by Michele Geronazzo, University of Padova. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% get empty object (the flag 'm' provides the mandatory fields only) +Obj=SOFAgetConventions('SimpleHeadphoneIR','m'); + +Obj.GLOBAL_Title = 'HPIR'; +Obj.GLOBAL_DatabaseName = BTDEI.specs.Database; + +Obj.GLOBAL_History = 'Converted from the BT-DEI format'; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HpTFs from DEI - University of Padova'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_AuthorContact = 'geronazzo@dei.unipd.it'; +Obj.GLOBAL_References = ['M. Geronazzo, F. Granza, S. Spagnol, F. Avanzini. ', ... + 'A Standardized Repository of Head-Related and Headphone Impulse Response Data ', ... + 'In 134th Convention of the Audio Engineering Society, May 2013.']; +Obj.GLOBAL_Organization = 'Department of Information Engineering, University of Padova'; +Obj.GLOBAL_Comment = ''; + +% copy the data + +% Emitter - Source +Obj.GLOBAL_SourceDescription = [BTDEI.hp.Id ' - ' BTDEI.hp.Producer ' ' BTDEI.hp.Model]; +Obj.GLOBAL_SourceManufacturer = BTDEI.hp.Producer; +Obj.GLOBAL_SourceModel = BTDEI.hp.Model; +%Obj.GLOBAL_SourceURI = BTDEI.hp.Uri; +% Receiver - Listener +Obj.GLOBAL_SubjectID = BTDEI.specs.SubjectId; +Obj.GLOBAL_ListenerDescription = BTDEI.sbjType; +Obj.GLOBAL_ReceiverDescription = BTDEI.specs.MicrophonePosition; % qualitative data e.g. blocked ear canal, open ear canal, at the eardrum + + +Obj.ListenerPosition = [0 0 0]; +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 0]; +Obj.SourcePosition = [0 0 0]; +Obj.EmitterPosition = [0 0.09 0; 0 -0.09 0]; + +%% Fill data with data +Obj.Data.SamplingRate = BTDEI.specs.SampleRate; % Sampling rate + +% calculate the effective size of the data matrix +M = length(BTDEI.data); % number of repositionings +R = size(BTDEI.data(1).HpIR,2); % number of channels (stereo) + +len_vec = zeros(M,1); +for ii=1:M + len_vec(ii)= length(BTDEI.data(ii).HpIR); +end +N = max(len_vec); + +Obj.API.M=M; +Obj.API.R=R; +Obj.API.N=N; + +% store IR data +Obj.Data.IR = NaN(M,R,N); % data.IR must be [M R N] +for aa=1:M + HpIR = [BTDEI.data(aa).HpIR; zeros((N-length(BTDEI.data(aa).HpIR)),2)]; + Obj.Data.IR(aa,1,:)= HpIR(:,1)'; + Obj.Data.IR(aa,2,:)= HpIR(:,2)'; +end + + +% update dimensions +Obj = SOFAupdateDimensions(Obj); +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..1d8c818b355c939b002b11fbefa3cf58f980ade8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m @@ -0,0 +1,61 @@ +function Obj=SOFAconvertCIPIC2SOFA(CIPIC) +% Obj=SOFAconvertCIPIC2SOFA(CIPIC) converts the HRTFs described in the structure CIPIC +% (see CIPIC HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +ida=round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1)); +lat=lat1(ida); + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,size(CIPIC.hrir_l,3)); % data.IR must be [M R N] +Obj.Data.SamplingRate = 44100; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=CIPIC.hrir_l(aa,ee,:); + Obj.Data.IR(ii,2,:)=CIPIC.hrir_r(aa,ee,:); + [azi,ele]=hor2sph(-lat(ii),pol(ii)); + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = CIPIC.name; +Obj.GLOBAL_History = 'Converted from the CIPIC file format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; +% SimpleFreeFieldHRIR 0.3 and 0.4 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..5fc3fb679bbe611737d93a84337a61d578702a0a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m @@ -0,0 +1,83 @@ +function Obj=SOFAconvertFHK2SOFA(miroObj) +% OBJ=SOFAconvertFHK2SOFA(miroObj) converts the HRTFs described in miroObj +% to SOFA. miroObj is the miro object saved at the Fach-Hochschule Köln +% provided by Benjamin Bernschütz. +% Reference to the source format: http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +% Reference to the source coordinate system: [1] http://code.google.com/p/sofia-toolbox/wiki/COORDINATES + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% if isoctave, +if exist('OCTAVE_VERSION','builtin') ~= 0 + error('Octave is not able to convert FHK to SOFA, use Matlab instead.'); +end + +%% Check if miro.m class file is available, if not download file from server +% miro class might also be included in other toolboxes, eg. AKtools +if exist('miro','class') ~= 8 + % download miro.m + disp('Downloading miro.m from TH Köln server...') + url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m'; + basepath=which('SOFAstart'); + basepath=basepath(1:end-12); % Kill the function name from the path. + target=[basepath filesep 'helpers' filesep 'miro.m']; + websave (target,url); +end + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = miroObj.irChOne; % irChOne is [N M] +Obj.Data.IR(:,:,2) = miroObj.irChTwo; +Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +% Obj.GLOBAL_APIName +% Obj.GLOBAL_ApplicationName +% Obj.GLOBAL_ApplicationVersion +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = miroObj.context; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Fachhochschule Köln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_References = 'Bernschütz, B. (2013). "A Spherical Far Field HRIR/HRTF Compilation of the Neumann KU 100", proceedings of the AIA/DAGA, Meran, Italy'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Origin = 'http://www.audiogroup.web.fh-koeln.de/ku100hrir.html'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='FHK'; +Obj.GLOBAL_Title = 'HRTF'; + +%% Fill the mandatory variables +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + % From [1]: All angles are in RAD. + % AZ denotes the azimutal angle in a range of (0-2pi(. Whereas AZ=0 is defined to be the front direction and AZ=pi to be the rear direction. + % EL denotes the elevation angle in a range of (0-pi). EL=0 points upwards, EL=pi/2 points to the horizontal plane and EL=pi points downwards. + % r is the radius in meters (if needed/specified). +Obj.SourcePosition = [... + rad2deg(miroObj.azimuth') ... % miroObj.azimuth is AZ + 90-rad2deg(miroObj.elevation') ... % miroObj.elevation is EL + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % miro.sourceDistance is r + +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +%Obj.GLOBAL_EmitterDescription =''; +Obj.GLOBAL_RoomDescription = miroObj.location; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..3005699ddefb22c1e876563129116d625051af5a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m @@ -0,0 +1,45 @@ +function Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) +% Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) converts the HRTFs described in LISTEN +% (see LISTEN HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data + % content_m is [M N], data.IR must be [M R N] +Obj.Data.IR = zeros(size(LISTEN.l_eq_hrir_S.content_m,1),2,size(LISTEN.l_eq_hrir_S.content_m,2)); +Obj.Data.IR(:,2,:)=LISTEN.r_eq_hrir_S.content_m; +Obj.Data.IR(:,1,:)=LISTEN.l_eq_hrir_S.content_m; +Obj.Data.SamplingRate = 48000; % Note: LISTEN.l_eq_hrir_S.sampling_hz contains 44100 which is wrong! + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = subjectID; +Obj.GLOBAL_History='Converted from the LISTEN format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.95 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v zeros(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v 1.95*ones(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8e3f2e47b763dd6ec3cb6e2161081e780b32b8d3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m @@ -0,0 +1,86 @@ +function Obj=SOFAconvertMIT2SOFA(root,pinna) +% OBJ=SOFAconvertMIT2SOFA(root,pinna) loads the MIT HRTFs saved in a +% directory ROOT for the PINNA and converts to a SOFA object. +% PINNA must be 'normal' or 'large'. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Create correct parts of the file name +% 'L' use full data from left pinna (normal pinna) +% 'R' use full data from right pinna (large red pinna) +% 'H' use compact data -> not supported now +switch pinna + case 'normal' + postfix='L'; idx=[1 2]; + prefix='full'; + case 'large' + postfix='R'; idx=[2 1]; + prefix='full'; + otherwise + error('Pinna not supported'); +end + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90]; +elecnt=[ 56 60 72 72 72 72 72 60 56 45 36 24 12 1]; + +%% Determine data size +M=sum(elecnt); +Obj.SourcePosition=zeros(M,3); +if isfile([root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav']) + Obj.Data.IR=zeros(M,2,length(audioread([root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav']))); +else + warning(['File not existing: ' root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav' ' --> Please download it to: ' root filesep prefix filesep 'elev0' filesep]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + flip_azi = mod(360-azi,360); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(flip_azi)) 'a.wav']; + Obj.Data.IR(ii,idx(1),:) = audioread(fn)'; % data.IR must be [M R N] + dirfn=dir(fn); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(azi)) 'a.wav']; + Obj.Data.IR(ii,idx(2),:) = audioread(fn)'; + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1.4]; + ii=ii+1; + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = ['KEMAR, ' pinna ' pinna']; +Obj.GLOBAL_History='Converted from the MIT format'; +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 +% Obj.ListenerPosition = [1.4 0 0]; +% Obj.ListenerView = [-1 0 0]; +% Obj.ListenerUp = [0 0 1]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..22ffd2e9a97fe84139aa0aa2376744af0099ed88 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m @@ -0,0 +1,75 @@ +function Obj=SOFAconvertSCUT2SOFA(root,r) +% OBJ=SOFAconvertSCUT2SOFA(root,pinna) loads the SCUT HRTFs saved in a +% directory ROOT for the radius R and converts to a SOFA object. +% R must be in meters. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-30 -15 0 15 30 45 60 75 90]; +elecnt=[ 72 72 72 72 72 72 36 24 1]; + +%% Create empty matrix +M=sum(elecnt)*length(r); +Obj.SourcePosition=zeros(M,3); +Obj.Data.IR=zeros(M,2,512); + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for jj=1:length(r) + for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + fn=fullfile(root, ['r' num2str(r(jj)*100)], ['ele' num2str(ele)], ['H' num2str(azi) 'c.pcm']); + dirfn=dir(fn); + if isempty(dirfn) % check if HRTF sources are available + error(['HRTF files not available in: ' fullfile(root, ['r' num2str(r(jj)*100)], ['ele' num2str(ele)])]); + end + fid = fopen(fn, 'r'); + H = fread(fid,'float'); + fclose(fid); + Obj.Data.IR(ii,1,:) = single(H(1:2:1024)); % separate the left-ear HRIR + Obj.Data.IR(ii,2,:) = single(H(2:2:1024)); % separate the right-ear HRIR + Obj.SourcePosition(ii,:) = [mod(360-azi,360) ele r(jj)]; + ii=ii+1; + end + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the SCUT format'; + +Obj.GLOBAL_Author = 'Bosun Xie'; +Obj.GLOBAL_AuthorContact = 'phbsxie@scut.edu.cn'; +Obj.GLOBAL_License = 'CC 3.0 BY-SA-NC'; +Obj.GLOBAL_Organization = 'South China University of Technology, Guangzhou, China'; + +Obj.GLOBAL_References = 'Bosun Xie, 2013, "Head-Related Transfer Function and Virtual Auditory Display", J Ross Publishing Inc., Plantation, FL, USA'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_DatabaseName='SCUT'; + +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + + +%% Fill the mandatory variables +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..0391042cc29b57888ad059573cce7d16ffc4c544 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m @@ -0,0 +1,70 @@ +function [hM,meta,stimPar]=SOFAconvertSOFA2ARI(Obj) +% [hM, meta, stimPar]=SOFAconvertSOFA2ARI(Obj) converts a SOFA object HRTFs +% to HRTFs described in hM, meta, and stimPar (see ARI HRTF format). +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR'), + error('ARI Format supports only SimpleFreeFieldHRIR SOFA conventions'); +end + +%% Fill data matrix +hM=shiftdim(Obj.Data.IR,2); % data.IR is [M R N], hM must be [N M R] + +%% Fill stimPar +stimPar.SamplingRate = Obj.Data.SamplingRate; +stimPar.TimeBase = 1e6/stimPar.SamplingRate; +stimPar.SubjectID = Obj.GLOBAL_ListenerShortName; + +%% Fill meta + % Fill in geodesic coordinate system where azi=(0;360) and ele=(-90;90); +meta.pos(:,1)=bsxfun(@times,Obj.SourcePosition(:,1),ones(Obj.API.M,1)); +meta.pos(:,2)=bsxfun(@times,Obj.SourcePosition(:,2),ones(Obj.API.M,1)); + % Fill in the Channel +if isfield(Obj,'MeasurementSourceAudioChannel'), + meta.pos(:,3) = bsxfun(@times,Obj.MeasurementSourceAudioChannel,ones(Obj.API.M,1)); +else + meta.pos(:,3) = NaN(Obj.API.M,1); +end +if isfield(Obj,'MeasurementAudioLatency'), + meta.lat=bsxfun(@times,Obj.MeasurementAudioLatency,ones(Obj.API.M,1)); +end + % create horizontal-polar coordinates +[meta.pos(:,6), meta.pos(:,7)]=sph2hor(meta.pos(:,1),meta.pos(:,2)); + % create continuous-elevation coordinates where azi=(-90;90) and ele=(0;360); +meta.pos(:,4)=meta.pos(:,1); +meta.pos(:,5)=meta.pos(:,2); +idx=find(meta.pos(:,1)>90 & meta.pos(:,1)<=270); +meta.pos(idx,4)=meta.pos(idx,4)-180; +meta.pos(idx,5)=180-meta.pos(idx,5); +idx=find(meta.pos(:,1)>270 & meta.pos(:,1)<=360); +meta.pos(idx,4)=meta.pos(idx,4)-360; + +%% Fill with unknown but probably mandatory data +% stimPar.Channel = 0; +% stimPar.Electrode = 0; +% stimPar.PulseNr = 0; +% stimPar.Period = 0; +% stimPar.Offset = 0; +stimPar.Resolution = 24; % assume a 24-bit ADC/DAC resolution +% stimPar.FadeIn = 0; +% stimPar.FadeOut = 0; +% stimPar.Length = 0; +% stimPar.FittFileName = ''; +% stimPar.StimFileName = ''; +stimPar.GenMode = 1; +% stimPar.WorkDir = ''; +stimPar.ID = 'hrtf'; +stimPar.Version = '2.0.0'; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..dc01c37d17278e811c683381bcd8151b1ed24129 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m @@ -0,0 +1,79 @@ +function [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) +% [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) converts objects +% from SYMARE database to Struct in SOFA format. +% +% SYMAREpath of type string specifies the path where the SYMARE directory +% is found +% HRIRname of type string specifies which HRIR out of the +% <SYMAREpath>/HRIRs/Acoustic directory should be converted +% +% Returns Obj in SOFA format which can further be converted into .sofa +% file using SOFAsave + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: license added, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Get an empty conventions structure + +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); +Obj.GLOBAL_Title = 'HRIR'; +Obj.GLOBAL_RoomType = 'free field'; + +%% Fill global attributes +if isempty(strfind(HRIRname,'.mat')) + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-1:end)); +else + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-5:end-4)); +end + +Obj.GLOBAL_AuthorContact ='https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_Comment = ''; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History', ... + 'Converted from the SYMARE database'); +Obj.GLOBAL_License = strcat('Creative Commons Attribution-Non', ... + 'Commercial-ShareAlike 4.0 International Public License'); +Obj.GLOBAL_Organization = 'University of Sydney'; +Obj.GLOBAL_Author = 'Craig Jin, Anthony Tew, et al.'; +Obj.GLOBAL_Origin = 'https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_DateCreated = char(datetime('now','Format','yyyy-MM-dd HH:mm:ss.SSS')); +Obj.GLOBAL_DatabaseName='SYMARE'; + +%% Get SYMARE data and convert to SOFA structure +%m: number of measurements; +%R: number of receivers; +%n: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%HRIR Dimensions : mRn; + +% Get source positions +load(fullfile(SYMAREpath,'HRIRs','Parameters','azim')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','elev')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','r')); +if ~(length(r) == length(azim)) + r(1:size(azim)) = r; + r = r'; +end +Obj.SourcePosition = [azim*180/pi,elev*180/pi,r]; + +% Get sampling frequency +load(fullfile(SYMAREpath,'HRIRs','Parameters','fs')); +Obj.Data.SamplingRate = fs; + +% Get IRs +load(fullfile(SYMAREpath,'HRIRs','Acoustic',HRIRname)); % gets you hR, hL +HRIR(:,:,1) = hL'; % nm -> mnR +HRIR(:,:,2) = hR'; % nm -> mnR +Obj.Data.IR = permute(HRIR,[1 3 2]); % mnR -> mRn + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..027181b2e657e1f122585d21cf2ac37fb2ce04ca --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m @@ -0,0 +1,155 @@ +function Obj = SOFAconvertTHK2SOFA(miroObj) +% OBJ=SOFAconvertTHK2SOFA(miroObj) converts the HRIRs, BRIRs, and DRIRs +% (VariSphear array measurements) described in miroObj to SOFA. +% miroObj is the miro object saved at the Technische Hochschule Koeln, provided by Benjamin Bernschuetz. +% Reference to the source format: http://www.audiogroup.web.th-koeln.de/FILES/miro_documentation.pdf +% Reference to the source coordinate system: [1] http://www.audiogroup.web.th-koeln.de/SOFiA_wiki/COORDINATES.html +% SOFAconvertTHK2SOFA written by Tim Lübeck, TH Köln, 2018 +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% +%if isoctave, +if exist('OCTAVE_VERSION','builtin') ~= 0 + error(['Octave is not able to convert THK to SOFA, use Matlab instead.']); +end + +%% Check if miro.m class file is available, if not download file from server +% miro class might also be included in other toolboxes, eg. AKtools +if exist('miro','class') ~= 8 + % download miro.m + disp('Downloading miro.m from TH Köln server...') + url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m'; + basepath=which('SOFAstart'); + basepath=basepath(1:end-12); % Kill the function name from the path. + target=[basepath filesep 'helpers' filesep 'miro.m']; + websave (target,url); +end + +%% Get an empty conventions structure depending on miro format +if ( strcmp (miroObj.type,'HRIR') ) + Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_Title = 'HRIR'; + Obj.GLOBAL_RoomType = 'free field'; + typeFlag = 0; +elseif ( strcmp (miroObj.type,'BRIR') ) + Obj = SOFAgetConventions('MultiSpeakerBRIR'); + Obj.GLOBAL_Title = 'BRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 1; +else %( strcmp (miroObj.type,'MICARRAY') ) + Obj = SOFAgetConventions('SingleRoomDRIR'); + Obj.GLOBAL_Title = 'DRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 2; +end + +%% Fill global attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = [miroObj.context,' / Sampling Grid: ',miroObj.quadGrid]; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Technische Hochschule Koeln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_Origin = 'http://audiogroup.web.th-koeln.de'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='THK'; +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +Obj.GLOBAL_EmitterDescription = miroObj.source; +Obj.GLOBAL_RoomDescription = [miroObj.location,' / avgAirTemp: ',num2str(miroObj.avgAirTemp),' / avgRelHumidity: ',num2str(miroObj.avgRelHumidity)]; + +%% Set miroObj to degree mode +miroObj.shutUp = 1; +miroObj = setDEG(miroObj); + +%% Get miroObject data and convert to SOFA structure +%M: number of measurements; +%R: number of receivers; +%N: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%FIR : [M R N]; + +if (typeFlag == 0 || typeFlag == 1) %BRIR or HRIR + irChOne = zeros(miroObj.returnTaps,miroObj.nIr); + irChTwo = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + IR = getIR( miroObj, channel ); + irChOne(:, channel) = IR(:,1); %[N M] + irChTwo(:, channel) = IR(:,2); %[N M] + end + if (typeFlag == 0) %HRIR + Obj.Data.IR = irChOne; % irChOne is [N M] + Obj.Data.IR(:,:,2) = irChTwo; + Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] + else % BRIR + Obj.Data.IR = zeros(size(irChOne,2), 2, 1, size( irChTwo,1)); %[N 2 1 M] + Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irChOne,-2),3); + Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irChTwo,-2),3); + end +else % DRIR + irData = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + irData(:,channel) = miroObj.getIR(channel); + end + Obj.Data.IR = zeros(1, miroObj.nIr ,miroObj.returnTaps); %[M R N] + for R = 1 : miroObj.nIr + Obj.Data.IR(1,R,:) = irData(:,R); + end + Obj.Data.Delay = zeros(1,miroObj.nIr); +end +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill the mandatory source emitter variables +Obj.ListenerPosition = [0 0 0]; % for BRIR and HRIR listener in center +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; % for HRIR and BRIR ears as receiver + +if (typeFlag == 0)%HRIR + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.SourcePosition = [... + miroObj.azimuth' ... % azimuth angle in a range of (0-360°(. Whereas AZ=0° is defined to be the front direction and AZ=180° to be the rear direction. + 90-miroObj.elevation' ... % elevation angle in range of (0-180°). EL=0 points upwards, EL=90° points to the horizontal plane and EL=180° points downwards. + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % radius in meters +elseif (typeFlag == 1) %BRIR + Obj.SourcePosition = [0 0 0]; % default edit manually! + Obj.EmitterPosition = [miroObj.sourceDistance 0 0]; % default position is center, otherwise define manually + Obj.EmitterPosition_Type = 'cartesian'; + Obj.EmitterUp = [0 0 1]; + Obj.EmitterView = [-1 0 0]; + Obj.ListenerView = [miroObj.azimuth', ... % see HRIR definitions + 90-miroObj.elevation', ... + zeros(size(miroObj.azimuth'))]; %miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ListenerUp = [0 0 1]; +else %DRIR + Obj.SourcePosition = [1,0,0]; % default edit manually! + Obj.EmitterPosition = [0,0,0]; + Obj.ListenerPosition = [0 0 0]; + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ReceiverPosition = [... + miroObj.azimuth' ... + 90-miroObj.elevation' ... + miroObj.radius*ones(size(miroObj.azimuth'))]; + Obj.ReceiverPosition_Type = 'spherical'; + Obj.ReceiverPosition_Units = 'degree, degree, metre'; +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..6f1150b3fafdaf770745aae0f1544c8ef2540233 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m @@ -0,0 +1,58 @@ +function Obj=SOFAconvertTUBerlin2SOFA(irs) +% OBJ=SOFAconvertTUBerlin2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(shiftdim(irs.left,-1),2); % irs.left is [N M], data.IR must be [M R N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-1),2); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HRTF from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['H. Wierstorf, M. Geier, A. Raake, S. Spors. ', ... + 'A Free Database of Head-Related Impulse Response Measurements in ', ... + 'the Horizontal Plane with Multiple Distances. ', ... + 'In 130th Convention of the Audio Engineering Society, May 2011.']; +Obj.GLOBAL_Origin = 'https://dev.qu.tu-berlin.de/projects/measurements/repository/show/2010-11-kemar-anechoic/mat'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = irs.ears; +Obj.GLOBAL_SourceDescription = irs.source; + +%% Fill the mandatory variables +% SimpleFreeFieldHRIR 0.6 +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.SourcePosition = [nav2sph(rad2deg(irs.apparent_azimuth)') ... + rad2deg(irs.apparent_elevation)' ... + distance.*ones(M,1)]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..4c24ed7d1de931345f17044705ff6d144bcf74ff --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m @@ -0,0 +1,74 @@ +function Obj=SOFAconvertTUBerlinBRIR2SOFA(irs) +% OBJ=SOFAconvertTUBerlinBRIR2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object, using the MultiSpeakerBRIR +% Convention. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('MultiSpeakerBRIR'); + +%% Fill data with data +Obj.Data.IR = zeros(size(irs.left,2),2,1,size(irs.left,1)); +Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irs.left,-2),3); % irs.left is [N M], data.IR must be [M R E N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-2),3); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'BRIR from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['']; +Obj.GLOBAL_Origin = 'TU Berlin'; +Obj.GLOBAL_Organization = 'Quality and Usability Lab, Technische Universitaet Berlin'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'BRIR TU Berlin'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = 'Large ears (KB0065 + KB0066) with G.R.A.S. 40AO pressure microphones'; +Obj.GLOBAL_SourceDescription = 'Genelec 8030A'; +Obj.GLOBAL_RoomType = 'reverberant'; +Obj.GLOBAL_RoomDescription = ''; + + +%% Fill the mandatory variables +% MultiSpeakerBRIR +% === Source === +Obj.SourcePosition = [0 0 0]; % center of loudspeaker array +Obj.EmitterPosition = irs.source_position'; +Obj.EmitterView = irs.head_position'; +Obj.EmitterUp = [0 0 1]; +% === Listener === +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.ListenerPosition = irs.head_position'; +[x,y,z] = sph2cart(fixnan(irs.head_azimuth'), ... + repmat(fixnan(irs.head_elevation'),size(irs.head_azimuth')), ... + repmat(distance,size(irs.head_azimuth'))); +Obj.ListenerView = [x,y,z]; +Obj.ListenerUp = [0 0 1]; +% Receiver position for a dummy head (imported from SimpleFreeFieldHRIR) +Obj.ReceiverPosition = [0,0.09,0; 0,-0.09,0]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end + +function x = fixnan(x) + if isnan(x), x=0; end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m new file mode 100644 index 0000000000000000000000000000000000000000..ac6cb698bbbb9bebf1c320e6fe4633fc230aef7d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m @@ -0,0 +1,172 @@ +function [dtf,ctf]=SOFAhrtf2dtf(hrtf,varargin) +%SOFAHRTF2DTF splits HRTFs into directional transfer functions (DTFs) and +%common transfer functions (CTFs) +% Usage: [dtf,ctf]=SOFAhrtf2dtf(hrtf) +% [dtf,ctf]=SOFAhrtf2dtf(hrtf,f1,f2) +% +% Input parameters: +% hrtf: SOFA object with SimpleFreeFieldHRIR convention +% +% Output arguments: +% dtf: SOFA object with the directional transfer functions +% ctf: SOFA object with the common transfer functions +% +% `SOFAhrtf2dtf(...)` calculates DTFs using the method from either +% Majdak et al. (2010; 'log' flag) or Middlebrooks (1999; 'rms' flag). +% The magnitude spectrum of the CTF is calculated by +% averaging the (log-)magnitude spectra across all HRTFs for each ear. +% The phase spectrum of the CTF is the minimum phase +% corresponding to the magnitude spectrum of the CTF. +% DTFs result from filtering the HRTF with the inverse complex CTF. +% +% `SOFAhrtf2dtf` accepts the following key-value pairs: +% +% 'f1',f1 start frequency of the filtering (in Hz; default: 50 Hz) +% 'f2',f2 end frequency of the filtering (in Hz; default: 18 kHz) +% 'atten',a broadband attenuation in order to avoid clipping (in dB; +% default: 20 dB) +% 'weights' w area weights for averaging. Vector of size [M 1] +% (M=number of HRIRs), or flase (default: false) +% +% `SOFAhrtf2dtf` accepts the following flags: +% +% 'log' evaluate CTF magnitude spectrum by average of log-magnitude +% spectra, equivalent to geometric mean of linear filters +% (c.f., Majdak et al., 2010; Baumgartner et al., 2014). +% This is the default. +% 'rms' evaluate CTF magnitude spectrum by RMS of linear +% magnitude spectra, equivalent to diffuse-field +% compensation (c.f., Middlebrooks, 1999; Moller et al., +% 1995). +% +% References: +% Baumgartner, R., Majdak, P., & Laback, B. (2014). Modeling sound-source +% localization in sagittal planes for human listeners. J. Acoust. Soc. Am. +% 136(2), 791-802. +% Majdak, P., Goupell, M. J., & Laback, B. (2010). 3-D localization of +% virtual sound sources: Effects of visual environment, pointing method, +% and training. Attention, Perception, & Psychophysics, 72(2), 454-469. +% Middlebrooks, J. C. (1999). Individual differences in external-ear +% transfer functions reduced by scaling in frequency. J. Acoust. Soc. Am., +% 106(3), 1480-1492. +% Moller, H., Hammershoi, D., Jensen, C. B., S?rensen, M. F. (1995). +% Design criteria for headphones. J. Audio Eng. Soc., 43(4), 218-232. + +% #Author: Robert Baumgartner (16.01.2014) +% #Author: Fabian Brinkmann: added rms, and weighted averaging (08.09.2016) +% #Author: Piotr Majdak: Octave ifft compatibility (23.02.2018) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Check Input +definput.keyvals.f1 = 50; % Hz +definput.keyvals.f2 = 18000; % Hz +definput.keyvals.atten = 20; % dB +definput.keyvals.weights = false; +definput.flags.avg = {'log','rms'}; + +[flags,kv]=SOFAarghelper({'f1','f2','atten', 'weights'},definput,varargin); + +%% Settings +kv.fs = hrtf.Data.SamplingRate; +hrtfmtx = shiftdim(hrtf.Data.IR,2); % dim 1: time, dim 2: source position, dim 3: receiver/ear +N = size(hrtfmtx,1); +Nfft = N; %2^nextpow2(N); + +%% Frequency bounds +df = kv.fs/Nfft; +f = 0:df:kv.fs-df; +idx = f >= kv.f1 & f <= kv.f2; +idx(Nfft/2+2:end) = fliplr(idx(2:Nfft/2)); + +%% CTF calculation + +% get magnitude response +hrtff=fft(hrtfmtx,Nfft); +if flags.do_rms + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg=sqrt(sum( abs(hrtff).^2 .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2 )); + else + ctffavg=sqrt(mean(abs(hrtff).^2,2)); + end +else % flags.do_log + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg= sum(log(abs(hrtff)+eps) .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2); + else + ctffavg=mean(log(abs(hrtff)+eps),2); + end +end + +% Force minimum phase +ctfflog=mean(log(abs(hrtff)+eps),2); +ctfcep = ifft(ctfflog,Nfft); +ctfcep(Nfft/2+2:Nfft,:,:) = 0; % flip acausal part to causal part or simply multiply +ctfcep(2:Nfft/2,:,:) = 2*ctfcep(2:Nfft/2,:,:); % causal part by 2 (due to symmetry) +ctfflog = fft(ctfcep,Nfft); +ctfp = exp(ctfflog); + +% get complex spectrum +if flags.do_rms + ctff = ctffavg .*exp(1j*angle(ctfp)); +else + ctff = exp(ctffavg) .*exp(1j*angle(ctfp)); +end + +% get IR +ctfmtx = real(ifft(ctff, Nfft)); + +%% DTF calculation +dtff = hrtff; +dtff(idx,:,:) = hrtff(idx,:,:)./repmat(ctff(idx,:,:),[1 size(hrtff,2) 1]); +dtfmtx = ifft(dtff,Nfft); + +%% Attenuate to avoid clipping +ctfmtx = ctfmtx / 10^(kv.atten/20); +dtfmtx = dtfmtx / 10^(kv.atten/20); + +%% Output Objects +dtf = hrtf; +if size(dtfmtx,3)==1 % handle objects with R=1 + dtfmtx(1,1,2)=0; + dtfmtx = shiftdim(dtfmtx,1); + dtf.Data.IR = dtfmtx(:,1,:); +else + dtf.Data.IR = shiftdim(dtfmtx,1); +end +if ~isfield(dtf, 'GLOBAL_Comment'), dtf.GLOBAL_Comment=''; end +dtf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Directional transfer functions (DTFs) were generated by removing from the HRTFs the direction-independent log-amplitude spectrum for each ear.']; + +ctf = hrtf; +if size(ctfmtx,2)==1 % handle objects with R=1 + ctf.Data.IR = shiftdim(shiftdata([ctfmtx ctfmtx],3),2); + ctf.Data.IR = ctf.Data.IR(1,:,:); +else + ctf.Data.IR = shiftdim(ctfmtx,1); +end +ctf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Common transfer functions (CTFs) were extracted from the HRTFs in terms of averaging the log-amplitude spectrum for each ear. The phase of a CTF is determined as minimum phase.']; +ctf.SourcePosition = [0 0 0]; + % remove non-standard variables +fc=fieldnames(ctf); +fo=fieldnames(SOFAgetConventions(ctf.GLOBAL_SOFAConventions)); +f=setdiff(fc,fo); % get non-standard fields +f(strncmpi(f,'GLOBAL_',7)) = []; % variables only +ctf=rmfield(ctf,f); % remove +ctf.API.Dimensions=rmfield(ctf.API.Dimensions,f); +ctf = SOFAupdateDimensions(ctf); + + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end; +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..780bb8e50218d149806f89e16ed5643b552b9dc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m @@ -0,0 +1,39 @@ +function [azi,ele]=hor2sph(lat,pol) +%HOR2SPH transform horizontal-polar to spherical coordinates. +% [azi,ele]=hor2sph(lat,pol) +% +% Input: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also SPH2HOR, SPH2NAV, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Robert Baumgartner +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - function hor2sph +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[x,nz,y] = sph2cart(-deg2rad(pol),deg2rad(lat),ones(size(lat))); + +[azi,ele,r] = cart2sph(x,y,-nz); + +azi = rad2deg(azi); +ele = rad2deg(ele); + +% adjust azimuth range +[azi,ele] = nav2sph(azi,ele); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..47e34d2bfc09f535f55b98b6f8ad586bacc9378f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m @@ -0,0 +1,28 @@ +function [azi,ele]=nav2sph(azi,ele) +%NAV2SPH Coordinate Transform. +% [azi,ele] = nav2sph(azi,ele) vonverts navigational coordinates to +% spherical coordinates. +% +% Input: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also HOR2SPH, SPH2HOR, SPH2NAV, SPH2HOR, SPH2SH + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function nav2sph +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +idx=find(azi<0); % azi between -180 and 0 deg +azi(idx) = azi(idx)+360; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m new file mode 100644 index 0000000000000000000000000000000000000000..d9ee4571c2360363c9c511f62b7c840a43990773 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m @@ -0,0 +1,64 @@ +function [S, N_SH] = sph2SH(dirs, L) +%[S, N_SH] = sph2SH(dirs, L); +% sph2SH calculates real-valued spherical harmonics for directions dirs = [azi ele] (in degrees) up to order L. +% +% Input: +% dirs ... dirs = [azi ele] +% L ... order L +% +% Output: +% S ... real-valued spherical harmonics +% N_SH ... number of SH coefficients +% +% See also HOR2SPH, SPH2HOR, SPH2NAV, SPH2HOR, NAV2SPH + +% #Author: Piotr Majdak: adapted from getSH.m from https://github.com/polarch/Spherical-Harmonic-Transform (24.07.2020) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - function sph2SH +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + + N_dirs = size(dirs, 1); % number of discrete positions + N_SH = (L+1)^2; % number of SH coefficients + dirs=deg2rad(dirs); % convert to radiant + dirs(:,2) = pi/2 - dirs(:,2); % convert to zenith angle + + S = zeros(N_SH, N_dirs);% matrix with the coefficients + + % n = 0, direction-independent component + Llm = legendre(0, cos(dirs(:,2)')); + Nlm = sqrt(1./(4*pi)) * ones(1,N_dirs); + CosSin = zeros(1,N_dirs); + CosSin(1,:) = ones(1,size(dirs,1)); + S(1, :) = Nlm .* Llm .* CosSin; + + % n > 0, direction-dependent components + idx = 1; + for l=1:L + + m = (0:l)'; + + Llm = legendre(l, cos(dirs(:,2)')); + condon = (-1).^[m(end:-1:2);m] * ones(1,N_dirs); + Llm = condon .* [Llm(end:-1:2, :); Llm]; + + mag = sqrt( (2*l+1)*factorial(l-m) ./ (4*pi*factorial(l+m)) ); + % create the ACN ordering: [m<0; m=0; m>0] + Nlm = [mag(end:-1:2) * ones(1,N_dirs); mag * ones(1,N_dirs)]; + + CosSin = zeros(2*l+1,N_dirs); + CosSin(l+1,:) = ones(1,size(dirs,1)); % m=0 + CosSin(m(2:end)+l+1,:) = sqrt(2)*cos(m(2:end)*dirs(:,1)'); % m>0 + CosSin(-m(end:-1:2)+l+1,:) = sqrt(2)*sin(m(end:-1:2)*dirs(:,1)'); % m<0 + + S(idx+1:idx+(2*l+1), :) = Nlm .* Llm .* CosSin; + idx = idx + 2*l+1; + end + + S = S.'; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m new file mode 100644 index 0000000000000000000000000000000000000000..420dca0c384161169a60aeecb94de7cb1676ca37 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m @@ -0,0 +1,42 @@ +function [lat,pol]=sph2hor(azi,ele) +%SPH2HOR transform spherical to horizontal-polar coordinates. +% [lat,pol]=sph2hor(azi,ele) +% +% Input: +% azi ... azimuth (in degrees) +% ele ... elevation (in degrees) +% +% Output: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% See also HOR2SPH, SPH2NAV, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Robert Baumgartner +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function sph2hor +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +[x,y,z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(size(azi))); + +% remove noise below eps +x(abs(x)<eps)=0; +y(abs(y)<eps)=0; +z(abs(z)<eps)=0; + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[pol,nlat,r] = cart2sph(x,z,-y); +pol = rad2deg(pol); +lat = rad2deg(-nlat); + +% adjust polar angle range +pol = mod(pol+90,360)-90; +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m new file mode 100644 index 0000000000000000000000000000000000000000..b7fe3a0c403676c717a68340517f6be50609b20e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m @@ -0,0 +1,31 @@ +function [azi,ele] = sph2nav(azi,ele) +%SPH2NAV Coordinate Transform +% [azi,ele] = sph2nav(azi,ele) converts spherical coordinates to +% navigational coordinates. +% +% Input: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% See also HOR2SPH, SPH2HOR, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function sph2nav +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +azi=mod(azi,360); % wrap to 0 to 360 +idx=find(azi>180 & azi<=360); % azi between 180 and 360 +azi(idx) = -(360-azi(idx)); + +end % end of function \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..fa7d95ab7951c36b00f6a13d273a8c41a131770e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m @@ -0,0 +1,46 @@ +% SOFA Toolbox - demo script +% Load HRTF in ARI format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert (use default if not defined) +if ~exist('subjectID','var'); subjectID='NH4'; end +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); + +if isfile(ARIfn) + disp(['Loading: ' ARIfn]); + ARI=load(ARIfn); +else + warning(['File not existing: ' ARIfn ' --> Please download it from http://www.oeaw.ac.at/isf/hrtf and save it to: ' fullfile(fileparts(SOFAdbPath), 'ARI', subjectID)]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + + +%% convert +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); +Obj.GLOBAL_DatabaseName = 'ARI'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['ARI_' subjectID '_' ARIfile '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..fd2d65d51aa277fe06fa29aa48b05178b58d688a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m @@ -0,0 +1,65 @@ +% SOFA Toolbox demo script +% load HRTF in BT-DEI format and save in SOFA format. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Headphone index of the files to convert +hp= 'H010'; +% Subject index of the files to convert +subject= 'S115'; +% Measurement index of the files to convert +setm= 'Set02'; %Set01 Set02 ... +% File name of the BTDEI file +BTDEIfold='COMPENSATED'; %RAW %COMPENSATED %EQUALIZED +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load BTDEI file \ load database structure data +f=filesep; +BTDEI_hp_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,'headphones_info.mat'); +BTDEI_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,subject,setm,BTDEIfold,'MAT',[hp '_' subject '_btdei.mat']); +disp(['Loading BT-DEI data']); + +try + datasheet = load(BTDEI_hp_add); + BTDEI.hp = datasheet.hp_specs; + + switch subject + case 'S115' + BTDEI.sbjType = 'dummy head with large pinna'; + case 'S116' + BTDEI.sbjType = 'dummy head without pinna'; + case 'S117' + BTDEI.sbjType = 'dummy head without pinna'; + otherwise + BTDEI.sbjType = 'human'; + end + + container = load(BTDEI_add); + BTDEI.specs = container.specs; + BTDEI.data = container.data; +catch e + error(['Load BTDEI file - Error message: ' e.message ' Try downloading the BT-DEI database from: http://padva.dei.unipd.it/?page_id=345 to the corresponding directory.']); +end + +BTDEI.type = BTDEIfold; +BTDEI.typeset = setm; + +%% convert +Obj = SOFAconvertBTDEI2SOFA(BTDEI); +Obj.GLOBAL_Comment = SOFAappendText(Obj,'GLOBAL_Comment',BTDEIfold); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['BTDEI-hp_' hp '_subj_' subject '-' setm '-' BTDEIfold '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..eb571b48a7bc3180ed0d3c54273e218c855120b2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m @@ -0,0 +1,36 @@ +% load HRTF in CIPIC format and save in SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID=3; +% File name of the CIPIC file +CIPICfile='hrir_final'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load CIPIC file +CIPICfn=fullfile(fileparts(SOFAdbPath), 'CIPIC', ['subject_' sprintf('%03d',subjectID)], [CIPICfile '.mat']); +disp(['Loading: ' CIPICfn]); +CIPIC=load(CIPICfn); + +%% convert +Obj=SOFAconvertCIPIC2SOFA(CIPIC); +Obj.GLOBAL_DatabaseName = 'CIPIC'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test', ['CIPIC_' 'subject_' sprintf('%03d',subjectID) '_' CIPICfile '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..19ef9ce31e245f834545a87d4c8a766ab67ae41f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m @@ -0,0 +1,62 @@ +% load HRTF in FHK format and save in SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Octave has no support for the miro class of the FHK data +% if isoctave +if exist('OCTAVE_VERSION','builtin') ~= 0 + warning(['demo_FHK2SOFA does not work in Octave.' newline 'Octave is not able to convert FHK to SOFA, use Matlab instead.']); + return; +end + +%% Check if miro.m class file is available, if not download file from server +% miro class might also be included in other toolboxes, eg. AKtools +if exist('miro','class') ~= 8 + % download miro.m + disp('Downloading miro.m from TH K�ln server...') + url = 'http://audiogroup.web.th-koeln.de/FILES/miro.m'; + basepath=which('SOFAstart'); + basepath=basepath(1:end-12); % Kill the function name from the path. + target=[basepath filesep 'helpers' filesep 'miro.m']; + websave (target,url); +end + +% load HRTF in FHK format and save as SOFA format + +%% Define parameters +% Get a file name of the FHK directory +d=dir(fullfile(fileparts(SOFAdbPath),'FHK','HRIR_*.mat')); +if isempty(d) + error(['No HRTF files available: ' fullfile(fileparts(SOFAdbPath),'FHK','HRIR_*.mat')]); +end +fn=d(1).name; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load FHK file +FHKfn=fullfile(fileparts(SOFAdbPath), 'FHK', fn); +disp(['Loading: ' FHKfn]); +FHK=load(FHKfn); +FHKvar=fieldnames(FHK); +FHKname=FHKvar{1}; +FHKdata=FHK.(FHKname); + +%% convert +Obj=SOFAconvertFHK2SOFA(FHKdata); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['FHK_' FHKname '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m new file mode 100644 index 0000000000000000000000000000000000000000..ca59a8a3a635465cc59078c3ccca141eb58b7033 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m @@ -0,0 +1,74 @@ +% Demonstrates the usage of the FreeFieldDirectivityTF conventions. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: '(demo_)plot_trumpet_directivity' added to this script (19.02.2022) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% close all; + +clear fn; +fn{1}='ITA_Dodecahedron.sofa'; +fn{2}='Trumpet_modern_et_ff_all_tensorData.sofa'; +% fn{3}='Trumpet_modern_et_ff_a4_rawData.sofa'; % (21 MB!!! uncomment if you don't mind, or have downloaded it already) + + +for ii=1:length(fn) + Obj=SOFAload(['db://database/tu-berlin (directivity)/' fn{ii}]); + + % % update dimensions to see if it works + % D=SOFAupdateDimensions(D, 'verbose',1); + + % plot the geometry because why not + SOFAplotGeometry(Obj); + + % move every figure a little to the right from previous one + H=gcf; + % if ~isoctave; if ii>1; movegui(H,[(H.Position(1)+(ii-1)*300) H.Position(2)]); end; end + if exist('OCTAVE_VERSION','builtin') == 0; if ii>1; movegui(H,[(H.Position(1)+(ii-1)*300) H.Position(2)]); end; end + + % set title + title(strrep(char(fn(ii)),'_',' ')); + disp([' Figure ' num2str(ii) ' of ' num2str(length(fn))+1 ' plotted: ' strrep(char(fn(ii)),'_',' ')]); +end + + +%% plot_trumpet_directivity +% original code from Fabian Brinkmann (12.2021), adapted by Michael Mihocic (2021-2022) +% requires AKp.m, check dependencies, otherwise skip this part +if exist('AKp.m', 'file') + + % load Data + H = SOFAload('db://database/tu-berlin%20(directivity)/Trumpet_modern_a4_fortissimo.sofa'); + + p = H.Data.Real(:,:,1) + 1j * H.Data.Imag(:,:,1); + p_log = 20*log10(p/max(abs(p))); + + % plot + AKf(20) + AKp(p_log, 'x2', 'g', H.ReceiverPosition(:, 1:2), 'dr', [-10 0], ... + 'hp_view', [30 45], 'cm', 'RdBu_flip', 'cb', 0, ... + 'sph_proc', 'interpSpline1'); + title '' + + AKtightenFigure; + disp(' Figure 3 of 3 plotted: Trumpet_modern_a4_fortissimo.sofa'); +else + warning(' Figure 3 of 3 skipped: Trumpet_modern_a4_fortissimo.sofa'); + disp(' To plot this figure you need to:'); + disp(' - download AKtools.zip (release) from: https://www.ak.tu-berlin.de/menue/publications/open_research_tools/aktools/'); + disp(' - extract the zip file'); + disp(' - run AKtoolsStart.m'); + disp(' - add the path of AKtoolsStart.m to Matlab (including subdirectories!)'); +end + +%% +disp(' '); +disp('### demo_FreeFieldDirectivityTF: done ###'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..8787ae7d5726992cded804cea54ee36f735dbd3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m @@ -0,0 +1,64 @@ +% Demonstrates the usage of the FreeFieldHRIR conventions. + +% #Author: Michael Mihocic (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='FreeFieldHRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..45dda7fba262b69dae814e5f6ef76e19ecb19418 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m @@ -0,0 +1,268 @@ +% Demonstrates the usage of spherical harmonics (SH) for HRTF interpolation. +% demo_FreeFieldHRTF loads an HRTF set, transforms to TF, then to SH, then +% samples the horizontal and median plane in steps of 0.5 degrees. Finally, +% the files are saved in SOFAdbPath as demo_FreeFieldHRTF_{TF, SH, TFrec}.sofa. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: save figures as optional parameter added, figures are saved with respective titles as names (10.11.2021) +% #Author: Michael Mihocic: minor bugs fixed (28.12.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +savefigures=0; % save all created figures as fig and png (0: no, 1: yes) +if savefigures==1 + close all; % clean-up first + warning('off', 'MATLAB:MKDIR:DirectoryExists'); % suppress warning if folder exists + mkdir ([mfilename('fullpath') ' figures']); % output folder for figures + folder=[mfilename('fullpath') ' figures' filesep]; +end + +%% Let's start, load a SimpleFreeFieldHRIR SOFA object +IR=SOFAload('db://database/thk/HRIR_L2354.sofa'); +fs=IR.Data.SamplingRate; +IR.GLOBAL_APIVersion=SOFAgetVersion; +%% Figures +figure; +SOFAplotHRTF(IR,'magmedian'); +tit='SimpleFreeFieldHRIR (FIR, mag), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +% print([folder tit '.png'], '-dpng'); +end + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_1_IR.sofa'),IR); + +%% Convert to TF +TF=SOFAgetConventions('SimpleFreeFieldHRTF'); +TF.ListenerPosition=IR.ListenerPosition; +TF.ListenerPosition_Type=IR.ListenerPosition_Type; +TF.ListenerPosition_Units=IR.ListenerPosition_Units; +TF.ListenerView=IR.ListenerView; +TF.ListenerView_Type=IR.ListenerView_Type; +TF.ListenerView_Units=IR.ListenerView_Units; +TF.ListenerUp=IR.ListenerUp; +TF.SourcePosition=IR.SourcePosition; +TF.SourcePosition_Type=IR.SourcePosition_Type; +TF.SourcePosition_Units=IR.SourcePosition_Units; +TF.EmitterPosition=IR.EmitterPosition; +TF.EmitterPosition_Type=IR.EmitterPosition_Type; +TF.EmitterPosition_Units=IR.EmitterPosition_Units; +TF.ReceiverPosition=IR.ReceiverPosition; +TF.ReceiverPosition_Type=IR.ReceiverPosition_Type; +TF.ReceiverPosition_Units=IR.ReceiverPosition_Units; + +TF.Data.Real=zeros(IR.API.M,IR.API.R,IR.API.N+1); +TF.Data.Imag=zeros(IR.API.M,IR.API.R,IR.API.N+1); +for ii=1:IR.API.M + for jj=1:IR.API.R + sp=fft(squeeze(IR.Data.IR(ii,jj,:)),2*IR.API.N); % Delay not considered! + TF.Data.Real(ii,jj,:)=real(sp(1:IR.API.N+1,:)); + TF.Data.Imag(ii,jj,:)=imag(sp(1:IR.API.N+1,:)); + end +end +TF.N=(0:fs/2/IR.API.N:fs/2)'; + +TF=SOFAupdateDimensions(TF); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_2_TF.sofa'),TF); + +%% Plot median plane and horizontal planes for reference +figure; +SOFAplotHRTF(TF,'magmedian'); +tit='SimpleFreeFieldHRTF (TF, mag), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(TF,'etchorizontal'); +tit='SimpleFreeFieldHRTF (TF, etc), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% Convert to an emitter-based representation, TFE +TFE=TF; +TFE.GLOBAL_SOFAConventions = 'GeneralTF-E'; +TFE.GLOBAL_DataType = 'TF-E'; +TFE.API.E=TF.API.M; +TFE.API.M=1; +TFE.Data=rmfield(TFE.Data,{'Real','Imag'}); +TFE.Data.Real(1,:,:,:)=shiftdim(TF.Data.Real,1); % MRN --> 1RNM --> MRNE with M=1 +TFE.API.Dimensions.Data.Real='MRNE'; +TFE.Data.Imag(1,:,:,:)=shiftdim(TF.Data.Imag,1); +TFE.API.Dimensions.Data.Imag='MRNE'; +TFE.EmitterPosition=TF.SourcePosition; +TFE.EmitterPosition_Type=TF.SourcePosition_Type; +TFE.EmitterPosition_Units=TF.SourcePosition_Units; +TFE.API.Dimensions.EmitterPosition='ECI'; +TFE.SourcePosition=[0 0 0]; +TFE.API.Dimensions.SourcePosition='IC'; + +TFE=SOFAupdateDimensions(TFE); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_3_TFE.sofa'),TFE); + +%% Convert to SH +SH=TFE; +SH.GLOBAL_SOFAConventions = 'FreeFieldHRTF'; + +Lmax=floor(sqrt(size(SH.EmitterPosition,1))-1); % Max SH order +L=40; % actual SH order +[S, SH.API.E]=sph2SH(SH.EmitterPosition(:,1:2), L); + +Sinv=pinv(S); +SH.Data.Real=zeros(1, SH.API.R, SH.API.N, SH.API.E); +SH.Data.Imag=zeros(1, SH.API.R, SH.API.N, SH.API.E); +for ii=1:TFE.API.R + for jj=1:TFE.API.N + SH.Data.Real(1,ii,jj,:)=Sinv*squeeze(TFE.Data.Real(1,ii,jj,:)); + SH.Data.Imag(1,ii,jj,:)=Sinv*squeeze(TFE.Data.Imag(1,ii,jj,:)); + end +end + +SH.EmitterPosition=mean(SH.EmitterPosition); +SH.EmitterPosition_Type='Spherical Harmonics'; + +SH = SOFAupdateDimensions(SH); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_4_SH.sofa'),SH); + +%% plot median and horizonal planes - spatially continuous +figure; +SOFAplotHRTF(SH,'magmedian'); %title(''); +tit='FreeFieldHRTF (TFE, mag) in Spherical Harmonics'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(SH,'etchorizontal'); %title (''); +tit='FreeFieldHRTF (TFE, etc) in Spherical Harmonics'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot spatially continuous geometry +SOFAplotGeometry(SH); +tit='FreeFieldHRTF (TFE, geometry) in Spherical Harmonics'; % title +% if ~isoctave +if exist('OCTAVE_VERSION','builtin') == 0 + fig=gcf; + fig.Position(3:4)=[600,400]; % increase size (supported in Matlab only) +end +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot spatial spectra +figure; +for y=1:4 + subplot(2,2,y); hold on; + fax=0:fs/(2*SH.API.N):(fs-(fs/(2*SH.API.N)))/2; + r=1; plot(fax,20*log10(squeeze(abs(SH.Data.Real(1,r,:,y)+1i*SH.Data.Imag(1,r,:,y))))); + r=2; plot(fax,20*log10(squeeze(abs(SH.Data.Real(1,r,:,y)+1i*SH.Data.Imag(1,r,:,y)))),'r'); + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + tit=['SH spectra, coefficient index (ACN)= ' num2str(y)]; + title(tit); +end +subplot(2,2,1);legend('First receiver','Second receiver'); +if savefigures==1 + tit='SH spectra'; + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot all coefficients for a given frequency +figure; hold on; +f=10000; k=round(f/fs*2*SH.API.N); +plot(squeeze(20*log10(abs(SH.Data.Real(1,1,k,:)+1i*SH.Data.Imag(1,1,k,:)))),'ob'); +hold on; +plot(squeeze(20*log10(abs(SH.Data.Real(1,2,k,:)+1i*SH.Data.Imag(1,2,k,:)))),'xr'); +% title(); +xlabel('Coefficients (ACN index)'); +ylabel('Magnitude (dB)'); +legend('First receiver','Second receiver'); + +tit=['SH representation, frequency = ' num2str(f) ' Hz']; % title +title(tit); +if savefigures==1 + tit='SH representations'; % title + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + + +%% interpolate for the horizontal and median planes to FreeFieldHRTF (TFE) +TFEint=SH; +elemin=-90; +ele=[elemin:1:90 89:-1:elemin zeros(1,length(1:355))]'; +azi=[zeros(length(elemin:1:90),1); 180*ones(length(89:-1:elemin),1); (1:355)']; +radius=SH.EmitterPosition(:,3)*ones(size(ele)); +TFEint.EmitterPosition=[azi ele radius]; +TFEint.EmitterPosition_Type='spherical'; +TFEint.EmitterPosition_Units=SH.EmitterPosition_Units; +Sint = sph2SH(TFEint.EmitterPosition(:,1:2), L); +TFEint.API.E=size(Sint,1); +TFEint.Data.Real=zeros(1,2,TFEint.API.N,TFEint.API.E); +TFEint.Data.Imag=zeros(1,2,TFEint.API.N,TFEint.API.E); +for ii=1:TFEint.API.R + for jj=1:TFEint.API.N + TFEint.Data.Real(1,ii,jj,:)=Sint*squeeze(SH.Data.Real(1,ii,jj,:)); + TFEint.Data.Imag(1,ii,jj,:)=Sint*squeeze(SH.Data.Imag(1,ii,jj,:)); + end +end + +TFEint=SOFAupdateDimensions(TFEint); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_5_TFEint.sofa'),TFEint); + +%% interpolate for the horizontal and median planes to SimpleFreeFieldHRTF (TF) +TFint=TF; +ele=[-90:0.5:90 89:-.5:-90 zeros(1,length(1:0.5:355))]'; +azi=[zeros(length(-90:.5:90),1); 180*ones(length(89:-.5:-90),1); (1:0.5:355)']; +radius=1.2*ones(size(ele)); +TFint.SourcePosition=[azi ele radius]; +Sint = sph2SH(TFint.SourcePosition(:,1:2), sqrt(SH.API.E)-1); +TFint.API.M=size(Sint,1); +TFint.Data.Real=zeros(TFint.API.M,2,TFint.API.N); +TFint.Data.Imag=zeros(TFint.API.M,2,TFint.API.N); +for ii=1:TFint.API.R + for jj=1:TFint.API.N + TFint.Data.Real(:,ii,jj)=Sint*squeeze(SH.Data.Real(1,ii,jj,:)); + TFint.Data.Imag(:,ii,jj)=Sint*squeeze(SH.Data.Imag(1,ii,jj,:)); + end +end + +TFint=SOFAupdateDimensions(TFint); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_6_TFint.sofa'),TFint); + +%% compare +figure; +SOFAplotHRTF(TFint,'magmedian'); %title(''); +tit='SimpleFreeFieldHRTF (TF, mag), interpolated'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(TFint,'etchorizontal'); % title(''); +tit='SimpleFreeFieldHRTF (TF, etc), interpolated'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m new file mode 100644 index 0000000000000000000000000000000000000000..a2b7c1a87c9419df29865307eaac767c61d9cbfd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m @@ -0,0 +1,40 @@ +% Demonstrates the usage of the General conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='General'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.API.E=1; +Obj.Data.IR=rand(4800,1); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m new file mode 100644 index 0000000000000000000000000000000000000000..842ef389d8bc513bc908725e64c079fe3fd52acf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m @@ -0,0 +1,65 @@ +% Demonstrates the usage of the GeneralFIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='GeneralFIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] +Obj.Data.Delay=[0 0]; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m new file mode 100644 index 0000000000000000000000000000000000000000..9f9f9fc2086f540f73c0dcf7fa72dc4ac079e037 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m @@ -0,0 +1,65 @@ +% Demonstrates the usage of the GeneralFIR-E conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='GeneralFIR-E'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] +Obj.Data.Delay=[0 0]; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m new file mode 100644 index 0000000000000000000000000000000000000000..bbe277b63ff5d6db5bd5b2081393f6ceabd5229b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m @@ -0,0 +1,43 @@ +% Demonstrates the usage of the GeneralTF conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +% clear; +conventions='GeneralTF'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.ReceiverPosition=[0,0.09,0]; +Obj.SourcePosition=[1,0,0;0,1,0;-1,0,0;0,-1,0]; +% Fill some random data +Obj.Data.Real=[-0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024]; +Obj.Data.Imag=[0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m new file mode 100644 index 0000000000000000000000000000000000000000..e9cdde7ca57add1f4cfa392b0df2653df3212c61 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m @@ -0,0 +1,45 @@ +% Demonstrates the usage of the GeneralTF-E conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +% clear; +conventions='GeneralTF-E'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.ReceiverPosition=[0,0.09,0]; +Obj.SourcePosition=[1,0,0;0,1,0;-1,0,0;0,-1,0]; +% Fill some random data +% Obj.Data.Real=[-0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024]; +% Obj.Data.Imag=[0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005]; +Obj.Data.Real=rand(4,4800); +Obj.Data.Imag=rand(4,4800); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..6190b9aa8b6b2d09a39f3dfd167dede77ac58be4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m @@ -0,0 +1,42 @@ +% load HRTF in LISTEN format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +if ~exist('subjectID','var'); subjectID='1002'; end +% File name of the LISTEN file +LISTENfile=['IRC_' subjectID '_C_HRIR']; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load LISTEN file +LISTENfn=fullfile(fileparts(SOFAdbPath),'LISTEN',['IRC_' subjectID],'COMPENSATED','MAT','HRIR',[LISTENfile '.mat']); +if isfile(LISTENfn) + disp(['Loading: ' LISTENfn]); + LISTEN=load(LISTENfn); +else + warning(['File not existing: ' LISTENfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath),'LISTEN',['IRC_' subjectID],'COMPENSATED','MAT','HRIR')]); + error(['Sorry.... ' mfilename ' cannot complete! The following file is missing: ' LISTENfile '.mat']); +end + +%% convert +Obj=SOFAconvertLISTEN2SOFA(LISTEN,subjectID); +Obj.GLOBAL_DatabaseName = 'LISTEN'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['LISTEN_' subjectID '_' LISTENfile '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..17bc908327b810b38c4bd17600fea728741b3a49 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m @@ -0,0 +1,37 @@ +% load HRTF in MIT format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Two ears are available: normal and large. Select one or define before running this script. +if ~exist('pinna','var') + pinna='normal'; +end + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +MITfn=fullfile(fileparts(SOFAdbPath),'MIT KEMAR'); +disp(['Loading: ' MITfn ', pinna:' pinna]); + +%% load and convert +Obj=SOFAconvertMIT2SOFA(MITfn,pinna); +Obj.GLOBAL_DatabaseName = 'MIT'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['MIT_KEMAR_' pinna '_pinna.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..4a3ba286799a2c208ad7291b3f8db6b97e720dbb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the MultiSpeakerBRIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='MultiSpeakerBRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.Data.IR=rand(4800,2); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m new file mode 100644 index 0000000000000000000000000000000000000000..ac2b4ce34a757e3b5cad84d8552559b5a48fa1d9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m @@ -0,0 +1,35 @@ +% SOFA Toolbox - test script +% Test audio playback after convolving sound file + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% put your information here: +hrtf = SOFAload('path/to_your/HRTF.sofa'); % Load your impulse response into a struct +soundInput = audioread('path/to_your/fancy_audio_file.wav'); % Load your sound file + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(hrtf.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..e9e7c2139b7e2bb83c4ff7605039acd8a54d488b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m @@ -0,0 +1,40 @@ +% load HRTF in MIT format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Two ears are available: normal and large. Select one. +pinna='normal'; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +SCUTdata = 'nearfield'; +SCUTroot=fullfile(fileparts(SOFAdbPath),'SCUT',SCUTdata); +disp(['Loading: ' SCUTroot]); + +%% Define radii for converting +radius=[0.2 0.25 0.3:0.1:1]; +% radius=0.2; + +%% load and convert +Obj=SOFAconvertSCUT2SOFA(SCUTroot,radius); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +str=sprintf('%g,',radius); +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['SCUT_KEMAR_radius_' str(1:end-1) '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..24c31341b7cfb0a71f39d3632c4983b1ae78eea1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m @@ -0,0 +1,42 @@ +% load HRTF in SOFA format and save as ARI format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); +disp(['Loading: ' ARIfn]); +ARI=load(ARIfn); + +%% convert from ARI to SOFA +disp('Converting to SOFA...'); +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); + +%% convert back from SOFA to ARI +disp('Converting back to ARI (hM, meta, stimPar)...'); +[hM, meta, stimPar]=SOFAconvertSOFA2ARI(Obj); + +%% Calculate the differences +disp(['RMS difference between the new hM and the original ARI.hM: ' num2str(sum(sum(sqrt(mean((hM-ARI.hM).^2)))))]); +if sum(sum(sqrt(mean((hM-ARI.hM).^2))))>1, error('hM and ARI.hM not identic'); end +disp(['RMS difference between the new meta.pos and the original ARI.meta.pos: ' num2str(sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2))))]); +if sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2)))>1, error('meta.pos and ARI.meta.pos not identic'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m new file mode 100644 index 0000000000000000000000000000000000000000..def227d2fdfaf56cb82e61da8b90515424cbf977 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m @@ -0,0 +1,69 @@ +% load HRTF and plots CTF and average DTF +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define parameters +% Subject index of the file to convert +subject=3; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'database', 'cipic', ['subject_' sprintf('%03d',subject) '.sofa']); +X=SOFAload(SOFAfn); + +if exist('OCTAVE_VERSION','builtin') + % We're in Octave + pkg load signal; % for 'shiftdata' compatibility +end + +[D,C]=SOFAhrtf2dtf(X); + +% close all; +f = figure; +set(f, 'Position', [50, 400, 1100, 500]); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,1,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(C.Data.IR(1,1,1:length(C.Data.IR)/2)))))); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,2,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +[D,CC]=SOFAhrtf2dtf(D); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('left'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best') + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,1:length(C.Data.IR)/2))))),'r'); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,2,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('right'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m new file mode 100644 index 0000000000000000000000000000000000000000..339e4f6f304ac45411108b227fd99fa9ba382e60 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m @@ -0,0 +1,43 @@ +% load HRTF and plots ITD + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. +% + +%% Define parameters +% Subject index of the file to convert +subject=3; + +%% load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'database', 'cipic', ['subject_' sprintf('%03d',subject) '.sofa']); +Obj=SOFAload(SOFAfn, 'nochecks'); + +%% Calculate Interaural time delay +[itd_time, ~, ~, Obj_time] = SOFAcalculateITD(Obj, 'time', 'thr', 20); +[itd_samples, ~, ~, Obj_samples] = SOFAcalculateITD(Obj, 'samples', 'thr', 20); + +%% Plot results +h = figure(); +subplot(211) +plot((Obj_time.Data.Delay(:,1) - Obj_time.Data.Delay(:,2))*1e6) +xlabel('Position') +ylabel('Time (\mus)') +axis tight + +subplot(212) +plot((Obj_samples.Data.Delay(:,1) - Obj_samples.Data.Delay(:,2))) +xlabel('Position') +ylabel(['Samples (Fs:' num2str(Obj.Data.SamplingRate), 'Hz)']) +axis tight + +%% Polar plot (not working in Octave) +SOFAplotHRTF(Obj, 'itdhorizontal'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m new file mode 100644 index 0000000000000000000000000000000000000000..806bf50201abc12048719d1f7687e500c6fb4fbb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m @@ -0,0 +1,87 @@ +% load HRTF and extends low frequency content +% + +% #Author: Davi Carvalho +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. +% + +clear; % clc; close all; + +SOFAfile=fullfile(SOFAdbPath,'database','cipic','subject_003.sofa'); +Obj=SOFAload(SOFAfile); + + +%% Low frequency extension +fmin = 15; +fmax = 500; +Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax); + + +%% general properties +fs = Obj.Data.SamplingRate; +% HRIRs +IR = shiftdim(Obj.Data.IR, 2); +IR_lfe = shiftdim(Obj_lfe.Data.IR, 2); +% Number of samples +N = size(IR, 1); +N_lfe = size(IR_lfe, 1); +% Time vector +tx = 0:1/fs:(N-1)/fs; +tx_ext = 0:1/fs:(N_lfe-1)/fs; +% Frequency vector +freq = (0:N/2-1)*fs/N; +freq_lfe = (0:N_lfe/2-1)*fs/N_lfe; + + +%% PLOTS +ch = 1; % ear +pos = 100; % position index + +%%% Plot time +figure() +plot(tx, IR(:,pos,ch)); hold on +plot(tx_ext(1:N), IR_lfe(1:N, pos, ch), '--','linewidth', 1.3); hold off +legend('original', 'LFE', 'location', 'best') +xlabel('Time (ms)') +axis tight + +%%% Plot freq +figure() +ori = mag2db(abs(fft(IR(:,pos,ch), N_lfe))); +lfe = mag2db(abs(fft(IR_lfe(:,pos,ch)))); +semilogx(freq_lfe, ori(1:N_lfe/2)); hold on +semilogx(freq_lfe, lfe(1:N_lfe/2), '--','linewidth', 1.3); hold off +legend('original', 'LFE', 'location', 'best') +xlabel('Frequency (Hz)') +ylabel('Amplitude (dB)') +axis tight + +% %% Phase +% t = 0:1/1e3:10; +% fo = 0; +% f1 = 500; +% y = chirp(t,fo,t(end),f1,'linear',0,'complex'); +% figure +% semilogx(angle(fft(y))) +% title('phase') + +%% +figure +SOFAplotHRTF(Obj,'maghorizontal'); +figure +SOFAplotHRTF(Obj_lfe,'maghorizontal'); + + + + + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..c3c196a6318ab79290729766c95bf02bc2c8e708 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m @@ -0,0 +1,55 @@ +% This demo shows how to use SOFAexpand and SOFAcompact +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Expanding the objects +x=whos('Obj'); +disp('Expanding the objects'); +tic; +clear Expanded +for ii=1:length(radius) + Expanded(ii)=SOFAexpand(Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Expanded'); +disp([' Expanded object array is now larger by ' num2str(round((y.bytes-x.bytes)/1024)) ' kb']); + +%% Compress the object +disp('Compressing the objects'); +tic; +clear Compacted +for ii=1:length(radius) + Compacted(ii)=SOFAcompact(Expanded(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Compacted'); +disp([' Compacted object array is now as small as the original one. Difference: ' num2str(round((x.bytes-y.bytes)/1024)) ' kb']); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..79de42b828a2285512a4e65470b62b367526d969 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m @@ -0,0 +1,78 @@ +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Path definitions +SOFAfile=fullfile(SOFAdbPath, 'database', 'tu-berlin', 'qu_kemar_anechoic_all.sofa'); + +%% Loading the full object +disp(['Loading full object: ' SOFAfile]); +tic; +ObjFull=SOFAload(SOFAfile); +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% Loading metadata +disp('Loading all metadata and partial data only'); +tic; +Meta=SOFAload(SOFAfile,'nodata'); + +%% Get index of measurements with the same directions +azi=0; ele=0; +idx=find(Meta.SourcePosition(:,1)==azi & Meta.SourcePosition(:,2)==ele); + +%% Load the parts of the full objects +disp('Loading partial data only'); +clear Obj +for ii=1:length(idx); + Obj(ii)=SOFAload(SOFAfile,[idx(ii) 1]); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('Obj'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Load parts of multiple dimensions of the full object +%e.g. only left ear for source positions 0�-90� at distance 1m +tic +idxSTART=find(Meta.SourcePosition(:,1)==0 & Meta.SourcePosition(:,3)==1); +idxEND=find(Meta.SourcePosition(:,1)==90 & Meta.SourcePosition(:,3)==1); +idxCOUNT=idxEND-idxSTART+1; +disp('Loading partial data in multiple dimensions') +ObjPartMultDim=SOFAload(SOFAfile,[idxSTART idxCOUNT],'M',[1 1],'R'); +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('ObjPartMultDim'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Extract and plot the fully loaded data +IRsFull=squeeze(ObjFull.Data.IR(idx,1,:)); +legFull=num2str(ObjFull.SourcePosition(idx,3)); +subplot(1,2,1); +plot(IRsFull'); +legend(legFull); +title(['Demo of SOFAload:' 10 ... + 'Fully loaded data']); +xlabel(['Index (Sample Taps), fully loaded']); +ylabel('Amplitude'); + +%% Extract and plot the partially loaded data +IRs=zeros(length(idx), Obj(1).API.N); +for ii=1:length(idx) + IRs(ii,:)=squeeze(Obj(ii).Data.IR(:,1,:)); + leg{ii}=num2str(Obj(ii).SourcePosition(:,3)); +end +subplot(1,2,2); +plot(IRs'); +legend(leg); +title(['IRs for the left ear with radius as parameter' 10 ... + 'Partially loaded data']); +xlabel(['Index (Sample Taps), partially loaded']); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..0e3e28d79a25de3493595ba324024ecc14aca15d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m @@ -0,0 +1,64 @@ +% This demo shows how to use SOFAmerge +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA +% +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects to be merged +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Merging the objects +disp('Merging to a single SOFA object'); +tic; +ObjFull=Obj(1); +for ii=2:length(radius) + ObjFull=SOFAmerge(ObjFull,Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% save the object as a single SOFA file +warning('off','SOFA:save'); +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[TUBfile 'radius_' sprintf('%g_',radius) 'm.sofa']); +disp(['Saving: ' SOFAfn]); +tic; +Obj=SOFAsave(SOFAfn, ObjFull, compression); +x=whos('ObjFull'); +disp(['Saved ' num2str(round(x.bytes/1024)) ' kb in ' num2str(toc) ' s.']); + +%% Plot IRs for a single direction but different radius +azi=0; ele=0; +idx=find(Obj.SourcePosition(:,1)==azi & Obj.SourcePosition(:,2)==ele); +plot(squeeze(ObjFull.Data.IR(idx,1,:))'); +legend(num2str(ObjFull.SourcePosition(idx,3))) +title(['Demo of SOFAmerge:' 10 ... + 'IRs for the left ear with radius as parameter retrieved from a merged object']); +xlabel(' index (sample taps)'); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m new file mode 100644 index 0000000000000000000000000000000000000000..4650b0d87a738fa76b44c3d36f447cbc43cc7305 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m @@ -0,0 +1,64 @@ +% demo_SOFAplotGeometry - script demonstrating the usage of +% SOFAplotGeometry +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file in SimpleFreeFieldHRIR + +SOFAfile=fullfile(SOFAdbPath,'database','widespread','ICO1m_00139.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +% plot all measurements +SOFAplotGeometry(Obj); + +% % only show every 45th measurement +index = 1:45:Obj.API.M; +SOFAplotGeometry(Obj,index); + +% %% load a SingleRoomDRIR SOFA file +disp(['Loading: ' 'db://' fullfile('database','thk','DRIR_LBS_VSA_1202RS_SBL.sofa')]); +Obj=SOFAload(['db://' ... + fullfile('database','thk','DRIR_LBS_VSA_1202RS_SBL.sofa')]); + +% plot SOFA Object with 1202 Receivers +SOFAplotGeometry(Obj); + +% % remove all but one Receiver +Obj.ReceiverPosition = [0 0.09 0]; +Obj.ReceiverPosition_Type = 'cartesian'; +Obj.Data.IR = Obj.Data.IR(:,1,:); +Obj.Data.Delay = Obj.Data.Delay(:,1,:); +Obj = SOFAupdateDimensions(Obj); + +SOFAplotGeometry(Obj); + +% %% load a GeneralFIR SOFA file +SOFAfile=fullfile(SOFAdbPath,'database', 'tu-berlin','FABIAN_CTF_modeled.sofa'); +Obj = SOFAload(SOFAfile); + +SOFAplotGeometry(Obj); + +% %% load example with room geometry +disp(['Loading: ' SOFAfile]); +SOFAfile = fullfile(SOFAdbPath,'sofatoolbox_test', 'Oldenburg_OfficeII.sofa'); +Obj = SOFAload(SOFAfile); + +SOFAplotGeometry(Obj); + +% %% if exists try plotting SOFA file containing spherical harmonic emitter +% if exist(fullfile(SOFAdbPath,'demo_SHforHRTFs_SH.sofa')) +% Obj = SOFAload(fullfile(SOFAdbPath,'demo_SHforHRTFs_SH.sofa')); +% SOFAplotGeometry(Obj); +% else +% error('Run demoSHforHRTFS.m first.') +% end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..c1813c46e700aaaa333861bfae06f8a3205648f5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m @@ -0,0 +1,35 @@ +% demo_SOFAplotHRTF - script demonstrating the usage of SOFAplotHRTF + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file in SimpleFreeFieldHRIR +SOFAfile=fullfile(SOFAdbPath,'database','ari','dtf_nh2.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +% plot ETC horizontal plane +figure; +SOFAplotHRTF(Obj,'ETCHorizontal',1); +% plot magnitude spectrum in the median plane, channel 2 +figure; +SOFAplotHRTF(Obj,'MagMedian',2); + +%% load a GeneralTF SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari (sim)','hrtf_nh5_ref.sofa'); +Obj=SOFAload(SOFAfile); +% plot magnitude spectrum in the median plane, channel 1 +figure; +SOFAplotHRTF(Obj,'MagMedian',1); +figure; +SOFAplotHRTF(Obj,'MagMedian',1,'convert',0); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..2d42da3d56b25a2fdb38ee4efde0e655959a645a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m @@ -0,0 +1,73 @@ +%% +% This demo creates an artificial HRTF set. +% It shows how to use SOFAgetConventions and SOFAsave +% The HRTF set contains single pulses placed at sample index of 100 +% which results in a broadband delay of 100 samples. +% Each IR is 256 samples long (i.e., N=256) + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Set parameters +% Latency of the created IRs +latency=100; % in samples, must be 1<latency<256 +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Get an empy conventions structure +disp('Creating SOFA file with SimpleFreeFieldHRIR conventions...'); +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +%% Create the impulse response +N=256; +IR=[zeros(latency,1); 1; zeros(N-latency-1,1)]; + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History = 'created with a script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','Pulse.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..e7a0f0cb9717ab4cdd58676e1d385e67d15b33af --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m @@ -0,0 +1,60 @@ +% SOFA Toolbox - demo script + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define the filename of the SOFA HRTFs +database='ari'; HRTFfilename='hrtf_nh4.sofa'; +% database='cipic'; HRTFfilename='subject_003.sofa'; +% database='listen'; HRTFfilename='irc_1002.sofa'; +% database='mit'; HRTFfilename='mit_kemar_normal_pinna.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_0.5m.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_all.sofa'; + +%% Define the trajectory +azi=[-45 90 0]; % azimuth angles in degrees. If negative values are found, navigational system (-180;+180) will be used. +ele=[0 0 -30 90]; %elevation angles in degrees + +%% Load the HRTFs +fullfn=fullfile(SOFAdbPath, 'database', database, HRTFfilename); +disp(['Loading ' fullfn]); +Obj=SOFAload(fullfn); + +%% Create an input signal +in=randn(5*Obj.Data.SamplingRate,1); % Five seconds of noise +fade=round(0.02*Obj.Data.SamplingRate); % fade in and out for 20 ms +win=hanning(fade*2); +in(1:fade)=in(1:fade).*win(1:fade); +in(end-fade+1:end)=in(end-fade+1:end).*win(fade+1:end); +%% Spatialize +[out,azi,ele,idx]=SOFAspat(in,Obj,azi,ele); +disp('Binaural signal rendered'); + +%% Plot the trajectories +time = (1:length(azi))/Obj.Data.SamplingRate; + +figure +subplot(2,1,1); +plot(time,azi); % plot azimuthal trajectory +ylabel('Azimuth (deg)'); +title('SOFAspat: Trajectory'); + +subplot(2,1,2); +plot(time,ele); % plot elevational trajectory +ylabel('Elevation (deg)'); +xlabel('Time (s)'); + +%% Play the sound - use headphones! +if ~exist('dontplay','var'); + p=audioplayer(out, Obj.Data.SamplingRate); + play(p); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m new file mode 100644 index 0000000000000000000000000000000000000000..47616c7d35e2debcacac42fb257728371e36d11c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m @@ -0,0 +1,84 @@ +% Script for testing the string array feature of SOFA + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: updated with variable ReceiverDescriptions instead of Ears (03.08.2022) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Test Strings as application-specific variable +% Load some arbritrary HRTFs +hrtf = SOFAload(fullfile(SOFAdbPath, 'database','ari','dtf_nh2.sofa')); +% Add a string array +str={}; +for ii=1:hrtf.API.M + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +% SOFAaddVariable(Obj,Name,Dim,Value) +hrtf2 = SOFAaddVariable(hrtf,'Test','MS',str); + +% Add a new string with dimensions [RS] +strn={'left ear'; 'right ear'}; +hrtf2 = SOFAaddVariable(hrtf2, 'ReceiverDescriptions', 'RS', strn); + +% Save as SOFA +SOFAsave('stringtest_applicationvar.sofa',hrtf2); +% Reload the file +hrtf = SOFAload('stringtest_applicationvar.sofa'); +% compare the strings +if prod(strcmp(hrtf.Test,hrtf2.Test)) + disp('SimpleFreeFieldHRIR: String Load-Reload: OK'); + delete('stringtest_applicationvar.sofa'); +else + error('String comparison showed differences'); +end +clear + +%% Test with conventions GeneralString (non-standardized convention, just for testing) +% Create an empty object +Obj = SOFAgetConventions('GeneralString'); +% Create numeric data with M=15, R=2, N=10 +Obj.Data.Double=rand(15,2,10); +% Create string arrays +str2={}; str={}; +for ii=1:15 + id = num2str(round(rand(1,1)*1000000)); + str{ii,1}=['X' id]; + str2{ii,1}=['Left' id]; + str2{ii,2}=['Right' id]; +end +Obj.String2 = str2; % String1=[MRS] +Obj.Data.String1 = str; % Data.String1=[MS] +Obj.Data.String2 = str2; % Data.String2=[MRS] + +% Add a new string with dimensions [RS] +strn={'left ear'; 'right ear'}; +Obj = SOFAaddVariable(Obj, 'ReceiverDescriptions', 'RS', strn); + +% Update dimensions +Obj = SOFAupdateDimensions(Obj); +% Save as SOFA +SOFAsave('stringtest_generalstring.sofa',Obj); +% Reload the file +Obj2 = SOFAload('stringtest_generalstring.sofa'); +% Compare the strings +if ~prod(strcmp(Obj2.Data.String2,Obj.Data.String2)) + error('Data.String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.String2,Obj.String2)) + error('String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.Data.String1,Obj.Data.String1)) + error('Data.String1: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.ReceiverDescriptions,Obj.ReceiverDescriptions)) + error('ReceiverDescriptions: Comparison showed differences'); +end +disp('GeneralString: String1, String2, Data, ReceiverDescriptions: Load-Reload: OK'); +clear +delete('stringtest_generalstring.sofa'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m new file mode 100644 index 0000000000000000000000000000000000000000..5b0cff7487553798c5be7d70562fb365200952f4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m @@ -0,0 +1,64 @@ +% SOFA Toolbox - script demonstrating the usage of variables in the API + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari','hrtf_nh5.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +%% read an API internal variable +M=Obj.API.M; % read M, the number of measurements +disp(['The number of measurements, M, is ' num2str(M)]); + +%% add a user-defined variable and check it + % create a random variable with the size M +myvar=rand(M,1); + % add to Obj +Obj=SOFAaddVariable(Obj,'MyVariable','M',myvar); + % check if it's there and identical to the created one +if ~all((Obj.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the size is M +if ~all(size(Obj.MyVariable)==[M 1]), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% add a private variable + % create a random variable with the size 1000 x 10 +privatevar=rand(1000,10); + % add to Obj as private +Obj=SOFAaddVariable(Obj,'MyVariable','Private',privatevar); + % check if it's there and identical to the created one +if ~all((Obj.PRIVATE.MyVariable-privatevar)<=eps('single')), error('Error!'); end + % check if the size is 1000 x 10 +if ~all(size(Obj.PRIVATE.MyVariable)==[1000 10]), error('Error!'); end + +%% Save the object + % create a random file name +fn=[mfilename '_temp_' num2str(rand(1,1)) '.sofa']; +SOFAsave(fn,Obj); + +%% Reload the object and remove the temporary file +Obj2=SOFAload(fn); +delete(fn); + +%% Check if the user-defined variable is still there +if ~isfield(Obj2,'MyVariable'), error('Error!'); end + % check if the size is M +if ~all(size(Obj2.MyVariable)==[M 1]), error('Error!'); end + % check if it is identical to the created one +if ~all((Obj2.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj2.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% Make sure that the private variable is not there! +if isfield(Obj2,'PRIVATE'), error('Error!'); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m new file mode 100644 index 0000000000000000000000000000000000000000..4e6095731faf50a8eef000148949833aa5b822c9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m @@ -0,0 +1,108 @@ +% Convert data from SingleFreeFieldHRIR to SingleFreeFieldHRTF, +% extract a few frequency bins and save. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: plot figures as optional parameter added, figures are saved with titles (10.11.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% HRTF or DTF? +ARIfile='hrtf'; +% Which frequency bins to store? +bins=[10, 20, 50, 70]; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time +plotfigures=0; % 0: no figures; 1 show & save figures (and close others first) + +%% Load file in SimpleFreeFieldHRIR Conventions +f=filesep; +SOFAfn=fullfile(SOFAdbPath,'database','ari', [ARIfile '_' lower(subjectID) '.sofa']); + +if isfile(SOFAfn) + disp(['Loading: ' SOFAfn]); + IR=SOFAload(SOFAfn); +else + warning(['File not existing: ' SOFAfn ' --> Please download it from http://www.oeaw.ac.at/isf/hrtf and save it to: ' fullfile(SOFAdbPath,'database','ari', [ARIfile '_' lower(subjectID) '.sofa'])]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + +%% Plot figures +if plotfigures==1 + close all; + PlotFigures(IR, 'HRIR', '') +end + +%% Get a new SimpleFreeFieldTF conventions +TF=SOFAgetConventions('SimpleFreeFieldHRTF'); +disp('Converting SimpleFreeFieldHRIR to SimpleFreeFieldHRTF'); + +%% Copy variables and metadata +TFempty=rmfield(TF,fieldnames(SOFAgetConventions('SimpleFreeFieldHRTF','r'))); % skip all read-only metadata +Xf=fieldnames(rmfield(TFempty,{'API','Data'})); % skip other internal +for ii=1:length(Xf) + if isfield(IR, (Xf{ii})), TF.(Xf{ii})=IR.(Xf{ii}); end % copy if available +end + +%% Transform data +TF.Data.Real=zeros(IR.API.M,IR.API.R,length(bins)); +TF.Data.Imag=zeros(IR.API.M,IR.API.R,length(bins)); +TF.N=(bins*IR.Data.SamplingRate/IR.API.N)'; + +for ii=1:IR.API.M + cplx=fft((IR.Data.IR(ii,:,:))); + TF.Data.Real(ii,:,:)=real(cplx(:,:,bins)); + TF.Data.Imag(ii,:,:)=imag(cplx(:,:,bins)); +end + +%% Update dimensions +TF=SOFAupdateDimensions(TF); +%% Plot figures +if plotfigures==1 + PlotFigures(TF, 'HRTF', [', bins ' num2str(bins)]) +end + +%% Save +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['ARI_' ARIfile '_' subjectID '_' num2str(length(bins)) '_freqs.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn,IR,compression); + +function PlotFigures(data, type, bins) + figure; SOFAplotHRTF(data,'EtcHorizontal'); % energy-time curve in the horizontal plane (+/- THR) + tit=[type ' ETC Horizontal' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'EtcMedian'); % energy-time curve in the median plane (+/- THR) + tit=[type ' ETC Median' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'MagHorizontal'); % magnitude spectra in the horizontal plane (+/- THR) + tit=[type ' Magnitude Horizontal' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'MagMedian'); % magnitude spectra in the median plane (+/- THR) + tit=[type ' Magnitude Median' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'MagSpectrum'); % single magnitude spectrum for direction(s) DIR in COLOR +% tit=[type ' Magnitude Spectrum' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'MagSagittal'); % magnitude spectra in a sagittal plane specified by OFFSET +/- THR +% tit=[type ' Magnitude Sagittal' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'ITDhorizontal'); % ITD horizontal +% tit=[type ' ITD Horizontal' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m new file mode 100644 index 0000000000000000000000000000000000000000..af290e211e94c02bedd37e62fcded6bc515f8727 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the SimpleFreeFieldHRSOS conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SimpleFreeFieldHRSOS'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.SOS=rand(4800,2,6); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m new file mode 100644 index 0000000000000000000000000000000000000000..8db35f584dcc52c4a9e119a84e6c5cce6c0be784 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the SimpleFreeFieldSOS conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SimpleFreeFieldSOS'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.SOS=rand(4800,2,6); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m new file mode 100644 index 0000000000000000000000000000000000000000..91b10fdf6ae444f9cafecff94c79f76e000f0391 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m @@ -0,0 +1,60 @@ +% SOFA Toolbox - demo script for the convention SimpleHeadphoneIR. +% load headphone IRs from a SOFA file from the ARI headphones database + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define parameters +% Subject index of the file to convert +subjectID='NH5'; + +%% Load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'headphones', 'ari', ['hpir_' lower(subjectID) '.sofa']); +disp(['Loading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot amplitude spectra +figure; +hold on; box on; +cols='bgrmky'; + +%if ~isoctave +if exist('OCTAVE_VERSION','builtin') == 0 + if isfield(X, 'MeasurementDate') + meastime=[0; diff(X.MeasurementDate)]; % diff not working in Octave + else + meastime=diff(X.GLOBAL_DateCreated); % diff not working in Octave + end +end + +for ii=1:X.API.M + plot(20*log10(abs(fft(squeeze(X.Data.IR(ii,1,:)),X.Data.SamplingRate))),cols(ii)); + if ii>1 + % if ~isoctave; + if exist('OCTAVE_VERSION','builtin') == 0 + leg{ii}=['#' num2str(ii) ':' num2str(meastime(ii)) ' seconds later']; + else + leg{ii}=['#' num2str(ii)]; + end + end +end + +for ii=1:X.API.M + plot(20*log10(abs(fft(squeeze(X.Data.IR(ii,2,:)),X.Data.SamplingRate)))-20,cols(ii)); +end + +xlim([-200 18200]); + +axis([-200 18200 -65 15]); +leg{1}='#1, first measurement'; +legend(leg); + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m new file mode 100644 index 0000000000000000000000000000000000000000..5897b2feee3b844f811972058b9310ebd115e9da --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m @@ -0,0 +1,157 @@ +% demo for SingleRoomDRIR: save DRIR data from Uni Oldenburg (Office II) as +% SOFA file and plot the speaker and listener positions. +% It uses conventions SingleRoomDRIR and RoomType 'shoebox', defined by +% RoomCornerA and RoomCornerB. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Based on the bachelor thesis of Wolfgang Hrauda (2013). + +% Measurement situation: +% T_60 = 300 ms +% speaker positions: +% entrance, desk, desk, at window (A, B, C, D) +% conditions: +% for position A and D: door and window were open +% Listener: headorientation = {1 2} -> 0�/-90� (straight/looking over right shoulder) +% Receivers: +% ch 1 & 2: 'in-ear' IRs from in-ear microphoes (not available for Office I) +% 'bte' 6-channel BTE-IRs: +% ch 3 & 4: 'front' BTE-IRs front microphone pair +% ch 5 & 6: 'middle' BTE-IRs middle microphone pair +% ch 7 & 8: 'rear' BTE-IRs rear microphone pair +% ambient noise: telepohne, keyboard typing, ventilation (all for both +% orientations); opening and closing the door (15 times) + + +%% Define parameters + + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% --- loading Uni Oldenburg data ---- +PathO=fullfile(fileparts(SOFAdbPath), 'Oldenburg','HRIR_database_mat','hrir','office_II'); +disp(['Loading from: ' PathO filesep]); + +A1fn = [PathO filesep 'office_II_1_A.mat']; +B1fn = [PathO filesep 'office_II_1_B.mat']; +C1fn = [PathO filesep 'office_II_1_C.mat']; +D1fn = [PathO filesep 'office_II_1_D.mat']; +A2fn = [PathO filesep 'office_II_2_A.mat']; +B2fn = [PathO filesep 'office_II_2_B.mat']; +C2fn = [PathO filesep 'office_II_2_C.mat']; +D2fn = [PathO filesep 'office_II_2_D.mat']; + +% has dimension: N x R +if isfile(A1fn); A1 = load(A1fn); else, error(['File not existing: ' A1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); B1 = load(B1fn); else, error(['File not existing: ' B1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); C1 = load(C1fn); else, error(['File not existing: ' C1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); D1 = load(D1fn); else, error(['File not existing: ' D1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); A2 = load(A2fn); else, error(['File not existing: ' A2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); B2 = load(B2fn); else, error(['File not existing: ' B2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); C2 = load(C2fn); else, error(['File not existing: ' C2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); D2 = load(D2fn); else, error(['File not existing: ' D2fn ' --> Please download it to: ' PathO filesep]); end +% +% B1 = load([PathO filesep 'office_II_1_B.mat']); +% C1 = load([PathO filesep 'office_II_1_C.mat']); +% D1 = load([PathO filesep 'office_II_1_D.mat']); +% A2 = load([PathO filesep 'office_II_2_A.mat']); +% B2 = load([PathO filesep 'office_II_2_B.mat']); +% C2 = load([PathO filesep 'office_II_2_C.mat']); +% D2 = load([PathO filesep 'office_II_2_D.mat']); + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SingleRoomDRIR'); + +%% Listener and Receiver +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 9; ... % in-ear + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % front bte + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % middle bte + 0.02 0.09 0.02; 0.02 -0.09 0.02]; % rear bte +Obj.ListenerPosition = [2.16 4.4 1.1]; +Obj.ListenerUp = [0 0 1]; +Obj.ListenerView = [repmat([1 0 0],4,1); repmat([0 -1 0],4,1)]; + +%% Source and Transmitter + +Obj.EmitterPosition = [0 0 0]; +A = [0.52 5.27 1.8]; +B = [0.79 1.25 1.1]; +C = [2.52 1.23 1.1]; +D = [2.38 0 1.8]; +Obj.SourcePosition = [A; B; C; D; A; B; C; D;]; +Av = [-1 0 0]; +Bv = [1 0 0]; +Cv = [1 0 0]; +Dv = [1 0 0]; +Obj.SourceView = [Av; Bv; Cv; Dv; Av; Bv; Cv; Dv;]; +Obj.SourceUp = [0 0 1]; + +%% Fill Data with data +% change data matrix dimension: N x R -> M x R x N +A1.data = shiftdim(A1.data,1); +data(1,:,:) = A1.data; +B1.data = shiftdim(B1.data,1); +data(2,:,:) = B1.data; +C1.data = shiftdim(C1.data,1); +data(3,:,:) = C1.data; +D1.data = shiftdim(D1.data,1); +data(4,:,:) = D1.data; +A2.data = shiftdim(A2.data,1); +data(5,:,:) = A2.data; +B2.data = shiftdim(B2.data,1); +data(6,:,:) = B2.data; +C2.data = shiftdim(C2.data,1); +data(7,:,:) = C2.data; +D2.data = shiftdim(D2.data,1); +data(8,:,:) = D1.data; +Obj.Data.IR = data; +Obj.Data.Delay = zeros(1,size(Obj.Data.IR,2)); +Obj.Data.SamplingRate = A1.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'HATS'; +Obj.GLOBAL_History='Converted from the Uni Oldenburg database'; +Obj.GLOBAL_License='http://medi.uni-oldenburg.de/hrir/html/download.html'; +Obj.GLOBAL_References='H. Kayser, S. D. Ewert, J. Anem�ller, T. Rohdenburg, V. Hohmann, and B. Kollmeier, "Database of Multichannel In-Ear and Behind-the-Ear Head-Related and Binaural Room Impulse Responses," EURASIP Journal on Advances in Signal Processing, vol. 2009, doi:10.1155/2009/298605'; + +%% Setup the room +Obj.GLOBAL_RoomType='shoebox'; +Obj.GLOBAL_RoomDescription='Office II at the University of Oldenburg, T_60 = 300 ms'; + +Obj.RoomCornerA = [0; 0; 0]; +Obj.RoomCornerA_Type = 'cartesian'; +Obj.RoomCornerA_Units = 'meter'; +Obj.API.Dimensions.RoomCornerA='C'; + +Obj.RoomCornerB = [3.3; 6; 0]; +Obj.RoomCornerB_Type = 'cartesian'; +Obj.RoomCornerB_Units = 'meter'; +Obj.API.Dimensions.RoomCornerB='C'; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','Oldenburg_OfficeII.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); +clear Obj; + +%% Re-load the file +disp(['Reloading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot the 2D-plan of the measurement setup +SOFAplotGeometry(X); +title('Office II from Kayser et al. (2009) saved as SingleRoomDRIR'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..526efa265573bc73d5bb14d95c96d18cefaa566d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m @@ -0,0 +1,115 @@ +% Demonstrates the usage of SingleRoomMIMOSRIR. +% Idea: demo_SingleRoomMIMOSRIR loads SRIRs from IEM database, +% converts to SH as SingleRoomMIMOSRIR, does planewave decompositon, and stores +% the data as a .sofa file. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: bugs fixed regarding variables ReceiverDescriptions and EmitterDescriptions; source files folder moved to data directory; some minor fixes (03.08.2022) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Data +% https://phaidra.kug.ac.at/view/o:104376, LS: 3 oder 5 +% documentation: https://www.mdpi.com/2076-3417/10/11/3747 + +% Download IR dataset from https://phaidra.kug.ac.at/view/o:104376 +% Copy the folder 'IEM' to your data directory + +Obj = SOFAgetConventions('SingleRoomMIMOSRIR'); +Obj.GLOBAL_Title = 'LigetiHall_CubeletToSt450'; +Obj.GLOBAL_Organization = 'Institut für elektronische musik und akustik, Graz, Austria'; +Obj.GLOBAL_AuthorContact = 'julien.demuynke@eurecat.org, markus.zaunschirm@atmoky.com, zotter@iem.at'; +Obj.GLOBAL_References = 'Auralization of High-Order Directional Sources from First-Order RIR Measurements (2020)'; +Obj.GLOBAL_Comment = '1rst order RIR measurements with Cubelet loudspeaker array protoype (6 loudspeakers) and TSL ST450 microphone (4 channels) in the György Ligeti Saal, Graz, Austria. The source was surrounded by 4 reflecting baffles (0.9 x 1.8 m) in its rear halfspace.'; +Obj.GLOBAL_ListenerShortName = 'TSL ST450'; +Obj.GLOBAL_SourceShortName = 'Cubelet loudspeaker array protoype'; +Obj.GLOBAL_DatabaseName = 'IEM'; +Obj.GLOBAL_ListenerDescription = ' 4-channel Ambisonic B-format microphone array with r = 2 cm'; +Obj.GLOBAL_SourceDescription = ' Spherical (r = 7.5 cm) 6-channel loudspeaker array prototype with loudspeakers arranged on surfaces of a cube'; +Obj.GLOBAL_RoomDescription = 'György-Ligeti Room in building LG14 - MUMUTH in Universität für Musik und darstellende Kunst Graz, Austria. Shoebox shaped room of surface 511.15m2 and volume 5630m3 with floor made of wooden panels'; + +Obj.ReceiverPosition_Type = 'spherical harmonics';%B-format +Obj.EmitterPosition = [0 0 0.075;90 0 0.075;180 0 0.075;270 0 0.075;0 90 0.075;0 -90 0.075]; +Obj.SourcePosition = [4.2 0 0]; +Obj.SourceView = [-1 0 0];%The source and the listener are facing each other + +datapath=[fileparts(SOFAdbPath) filesep 'IEM' filesep]; +IR_list = dir([datapath '*.wav']); +if isempty(IR_list) + error([' Folder does not exist or is empty: ' strrep(datapath,['SOFA' filesep '..' filesep],'') newline ' Download IR dataset from https://phaidra.kug.ac.at/view/o:104376 and save the files to the folder ''IEM'' in your data directory.']) +end +IR_INFO = audioinfo([IR_list(1).folder filesep IR_list(1).name]); + +C = 3; +I = 1; +M = 1; +R = IR_INFO.NumChannels; +N = IR_INFO.TotalSamples; +E = length(IR_list); + +fs = IR_INFO.SampleRate; +Obj.Data.IR = zeros(M,R,N,E); +for i = 1:6 + IR = audioread([IR_list(i).folder filesep IR_list(i).name]); + Obj.Data.IR(1,:,:,i) = transpose(IR); +end +Obj.Data.SamplingRate = fs; +Obj.Data.Delay = zeros(M,R,E); + +Obj.ReceiverView = zeros(R,C,I); +Obj.ReceiverUp = zeros(R,C,I); +Obj.EmitterView = zeros(E,C,I); +Obj.EmitterUp = zeros(E,C,I); + +% Add ReceiverDescriptions as string array +str={}; +for ii=1:R + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +Obj = SOFAaddVariable(Obj,'ReceiverDescriptions','RS',str); + +% Add EmitterDescriptions as string array +str={}; +for ii=1:E + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +Obj = SOFAaddVariable(Obj,'EmitterDescriptions','ES',str); + +Obj = SOFAupdateDimensions(Obj); + +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','LigetiHall_CubeletToSt450_IRs.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); + +% +% Paper for the algorithms: +% Park, M. and Rafaely, B. (2005). "Sound-field analysis by plane-wave decomposition using spherical microphone array," +% JASA, 118, 3094 3103. https://doi.org/10.1121/1.2063108 + + +%% Story line... +% First, the coefficients pnm up to order N are calculated using Eq. 5, + +% pnm = sum j=1 to M, a_j p(omega_j) Yn m_j. + + +% and then the waves directional amplitude +% density at each frequency, i.e., plane-wave decomposition, is +% computed at the desired directions using Eq. 9. +% +% b_n (kr,ka) = 4pi i^n(j_n(kr) ? ...) Eq. 7 +% +% w (omega_l) = sum n=0 to N sum m=?n to n p_nm / b_n Y (omega_l) + +% to be saved: p_nm and b_n(kr,ka) or simple a. +% + +%% Also this might help: Khaykin, D. and Rafaely, B. (2012). "Acoustic analysis by spherical +% microphone array processing of room impulse responses," JASA, 132, 261�270. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..448b5e1840a604ee48c558f3d63078039da53656 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m @@ -0,0 +1,49 @@ +% Demonstrates the usage of the SingleRoomSRIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SingleRoomSRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.IR=rand(4800,1); +Obj.ListenerPosition=zeros(4800,3); Obj.ListenerPosition(:,1)=1; +Obj.SourcePosition=zeros(4800,3); Obj.SourcePosition(:,2)=1; + +% Add ReceiverDescriptions as string array +str={}; +for ii=1:Obj.API.R + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +Obj = SOFAaddVariable(Obj,'ReceiverDescriptions','RS',str); + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..58ce22adf7e6eabd7ee456bb6df95d0047691069 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m @@ -0,0 +1,62 @@ +% SOFA Toolbox - demo script + +% load HRTF in TU Berlin format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Prefix to the files +TUBfile = 'QU_KEMAR_anechoic_'; +% Define vector with radii to be loaded. Available files: 0.5, 1, 2, and 3 m +% radius=[0.5 1 2 3]; +radius=[0.5]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load, convert, and save the requested TU-Berlin files +for ii=1:length(radius) + % load + + TUBfn=fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR', [TUBfile num2str(radius(ii)) 'm.mat']); + + if isfile(TUBfn) + disp(['Loading: ' TUBfn]); + TUB=load(TUBfn); + else + if radius(ii) == 0.5 % catch if file name ends with "05m.mat" instead of "0.5m.mat" + TUBfn2=fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR', [TUBfile '05m.mat']); + if isfile(TUBfn2) + disp(['Loading: ' TUBfn2]); + TUB=load(TUBfn2); + else + warning(['File not existing: ' TUBfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR')]); + error(['Sorry.... ' mfilename ' cannot complete!']); + end + else + warning(['File not existing: ' TUBfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR')]); + error(['Sorry.... ' mfilename ' cannot complete!']); + end + end + + % convert and add application specific metadata + Obj=SOFAconvertTUBerlin2SOFA(TUB.irs); + Obj.GLOBAL_DatabaseName = 'TU-Berlin'; % maybe setting the name by function parameter + Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; + Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + Obj.GLOBAL_Organization = 'Technische Universit�t Berlin'; + Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; + % save + SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['TU-Berlin_' TUBfile 'radius_' sprintf('%g',radius(ii)) 'm.sofa']); + disp(['Saving: ' SOFAfn]); + Obj=SOFAsave(SOFAfn, Obj, compression); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/helpers/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/helpers/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..07054edbe87c5e92fed84549e985192dcb35905e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/helpers/readme.txt @@ -0,0 +1 @@ +this folder is prepared for third-party helper files and folders \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/history.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/history.txt new file mode 100644 index 0000000000000000000000000000000000000000..76a25d3a76277300a4ceb411cfe130e9b2fa2709 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/history.txt @@ -0,0 +1,363 @@ +************************************************************* +*** History of SOFA Toolbox for Matlab and Octave +*** Acoustics Research Institute, Austrian Academy of Sciences, Vienna +*** Project leader: Piotr Majdak, piotr.majdak@oeaw.ac.at +*** Contributors: +*** Michael Mihocic +*** Harald Ziegelwanger +*** Hagen Wierstorf +*** Wolfgang Hrauda +*** Fabian Brinkmann +*** Felix Perchfler +************************************************************* + +*** DEVELOPMENT STATUS *** + +*** v2.1 (first 2.x release) + + +*** v2.0 (not released, rebranded to SOFA Toolbox) + +## Rebranding ## +- main directory renamed to "SOFAtoolbox" +- repository renamed to "SOFAtoolbox" +- subfolder "HRTFs" renamed to "data"; some files adapted +- all SOFA files created by demo_ will be saved in sofatoolbox_test + +## Core Functionality ## +- .gitignore added, updated multiple times +- Support for spherical harmonics added. +- SOFAconvertCoordinates.m: type horizontal-polar removed (not (properly) defined in SOFA) +- SOFAarghelper: minor bugs fixed (changes FB) +- SOFAinfo: showing all global mandatory fields now, plus some more for SimpleFreeFieldHRIR +- demoPlaySound.m added +- Readme.md: Example fixed (demoPlaySound.m) +- headers of functions checked, updated, author format changed to machine-readable format (#author) +- NETCDFload: 'deblank' command added when loading strings to avoid trailing empty spaces in size of array dimension +- SOFAcalculateITD.m added, adapted from AMT itdestimator +- SOFAcalculateLFE.m added (by DC), db changed to mag2db (Octave support) +- SOFAstart: + - Bug fixed when using 'restart' option: SOFAdbPath and SOFAdbURL were not reset + - Bug in help comment fixed + - flag 'full' added: show all information, including all compiled conventions & versions + - changed order of display output messages ((c) first) + - Bug fixed when adding paths (added at bottom in some specific cases) + +## Toolbox Functionality +- Conventions: + - Conventions for SOFA 2.0 added + - SOFAgetConventions: Versioning of convention files .CSV added + - csv files renamed to always include SOFAConventionsVersion in file name (created .mat files are unaffected) + - FreeFieldDirectivityTF_1.0.csv: + - updated by David Ackermann (not sure if ReceiverPosition and EmitterPosition still need to be updated) + - Mandatory flag removed for: Global:Comment, ListenerUp, ListenerUp:Type, ListenerUp:Units + - Dimension of ReceiverPosition and EmitterDescription fixed + - FreeFieldHRTF_1.0.csv: GLOBAL:SOFAConventionsVersion version number fixed + - SingleRoomSRIR_1.0.csv: GLOBAL:SOFAConventionsVersion version number fixed, RoomCornerA, RoomCornerB, RoomCorners:Type, RoomCorners:Units: Mandatory flag removed + - Dimension of Data.SamplingRate fixed to "I, M" for: GeneralFIR-E_2.0.csv, GeneralFIR_2.0.csv, General_1.0.csv, SimpleFreeFieldHRIR_1.0.csv, SimpleFreeFieldHRSOS_1.0.csv, SimpleHeadphoneIR_1.0.csv, SingleRoomSRIR_1.0.csv + - Conventions2Wiki.m: Column headers flags and dimensions changed to a hyperlink linking to that corresponding part on the website + - several bugs fixed; non-ASCII quotes replaced by ' (changes FB) + - Conventions FreeFieldHRIR_1.0.csv added + - SOFAcompileConventions: + - ignores files beginning with '_' + - Bug fixed when running in Octave + - '10' replaced by 'newline' in strings to avoid warnings in Octave + - display messages changed to output variable dispOutput + - bug fixed: replaced version "2" by "2.0" to keep one minor digit everywhere + - flags fixed +- Demos: + - demo_FreeFieldHRTF.m added; updated several times, allows saving figures as fig & png (see parameter 'savefigures'), some bug fixes + - demo_FreeFieldDirectivityTF.m: adapted to actual data on sofaconventions.org -> working now; plot_trumpet_directivity included + - SOFAconvertMIT2SOFA.m, demo_FHK2SOFA.m, demo_SingleRoomDRIROldenburg.m, demo_SingleRoomMIMOSRIR.m, demo_TUBerlin2SOFA.m: error message if source files are not available + - demo_ARI2SOFA.m, demo_LISTEN2SOFA.m: bug fixed: subject_ID was always overwritten; error message if source files are not available + - demo_SimpleFreeFieldHRIR2TF.m: bug fixed: Object to be saved was wrong; error message if source files are not available; updated several times; parameter 'plotfigures' causes plotting all figures, and saving them (fig, png) if set to 1 + - demo_SimpleHeadphoneIR.m: if .MeasurementDate is not existing use .GLOBAL_DateCreated as measurement time (legend in figure) + - SOFAconvertSCUT2SOFA.m: bug fixed when source files are not available -> error message + - demo_BTDEI2SOFA.m: Minor bug fixed in error message text + - demo_SOFAcalculateITD.m added + - demo_SOFAcalculateLFE.m added (by DC) + - demo_SphericalHarmonicsMic added +- test_SOFAall.m: + - structured (first *->SOFA, then SOFA->*, then SOFA functions, then SOFA conventions), and sorted (alphabetically) + - missing demos added + - disp messages improved + - some bugs fixed; all conventions are included in at least one demo file; all demos are tested with Matlab & Octave (run test_SOFAall.m) + - Matlab: all demos are working in Matlab, without any visible warnings + - Octave: all demos are working without any errors except for FHK2SOFA (not working at all; skipped in Octave), and some minor restrictions cause by unsupported commands, see warning messages during process for details + - some bugs fixed; demos that require souce files that are not publicly available will be catched with a warning instead of an error +- Download links updated for: + - HRTFs\ARI\readme.txt + - HRTFs\CIPIC\readme.txt + - HRTFs\TU-Berlin KEMAR\readme.txt +- SOFAplotHRTF: + - 'convert' flag added -> 1: convert to FIR and then to TF domain. Can be set to 0 if data is available in TF domain (FreeFieldDirectivityTF, GeneralTF, SimpleFreeFieldHRTF conventions). By default the function chooses the best option. + - type 'ITDhorizontal' added (changes DC) + - Octave support (except for type itdhorizontal) + - dependency on function 'npi2pi' removed (required toolbox in Matlab; in Octave not supported; outdated anyway) + - keyvalue 'R'/'r' renamed to 'receiver' + - Obj.GLOBAL_Title only displayed in figure title if not empty; title handling improved +- SOFAplotGeometry: + - bug fixed when extracting LU (listener up) coordinates + - minor bugs fixed +- headers of functions checked, updated, author format changed to machine-readable format (#author) +- helper folder renamed to helpers; folder is prepared for downloadable third-party functions +- helper functions removed; some functions are already supported by MATLAB, a few functionalities were implemented in the files themselves +- isoctave.m removed, replaced by code in files +- miro.m removed from repository; class file is downloaded if needed (by demo_FHK2SOFA, SOFAconvertFHK2SOFA, SOFAconvertTHK2SOFA); file might also be included in other toolboxes and can be used from them + +## TO-DO ## +- SOFAplotGeometry: complete rewrite with extensive support +- SOFAplotGeometry shows a cloud for spatially continuous emitters and receivers + + +************************************************************************************************************ + + +*** v1.1.2 +- SOFAplotGeometry: bug fix if no SourceView given +- FreeFieldDirectivityTF: missing eCM in EmitterPosition fixed +- SOFAcheckFilename: do not convert if filename is http:// +- SOFAplotHRTF: plot TF with regular frequency grid. Not tested for irregular grids, though... + +*** v1.1.1 +- SOFAstart: bug fix when starting for the first time +- SOFAconvertTUBerlinBRIR2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertTHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertFHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAappendText.m: example added to help +- SOFAcompileConventions: fix for changes in Octave 4.2 +- FreeFieldDirectivityTF: updated to version 0.2 + +*** v1.1.0 (not released) +- SOFAremoveVariable added. It removes a variable from the SOFA object. +- SOFAplotGeometry: show SourceView, and bug fix ListenerView. +- SOFAdbPath, SOFAdbURL: reset the path/URL to the default if the parameter is 'reset'. +- SOFAhrtf2dtf: handling for R=1 added. +- SOFAfind added: Find an index for a given position (draft, to be improved). +- SOFAload: provide error message on loading unknown conventions + +*** v1.0.4 (29.4.2019) +- on "SOFA upgrade warning", display a message on how to switch it off +- SOFAplotHRTF: 'magsagittal' added to plot HRTFs along a sagittal plane. +- SOFAload can use filenames beginning with "db://" to indicate to load from the database (local or remote) +- SOFAstart avoids repeated starts now - + - once SOFAstart has been started, SOFAstart won't be executed fully again, when the paths are still available. + - Call SOFAstart('restart') if a restart needs to be forced. + + +*** v1.0.3 (5.9.2018) +- automatic load of the netcdf package in Octave on SOFAstart +- SOFAspat: bugs in normalization, actual position selection removed +- SOFAhrtf2dtf: RMS and weighted averaging added, Octave compatibility ensured +- SOFAcompileConventions: bug fix when compiling conventions in Octave 4.2.1 +- test_SOFAall: suppress irrelevant warnings +- SOFAconvertMIT2SOFA: wavread replaced by audioread +- SOFAconvertConventions: it can convert from SimpleFreeFieldTF to SimpleFreeFieldHRIR. +- SOFAplotHRTF: more variable input of parameters, normalization optional +- SOFAconvertTHK2SOFA: converter from THK format (in miro format) to SOFA added. + +*** v1.0.2 (16.8.2016) +- SOFAplotHRTF: extended to SimpleFreeFieldTF and some cases of GeneralTF +- SOFAplotGeometry: extended to SimpleFreeFieldTF +- SOFAconvertTUBerling2SOFA: uses MultiSpeakerBRIR now +- SOFAspat, SOFAcalculateAPV: minor bug fixes + +*** v1.0.1 (10.6.2015) +- miro class is not supported in Octave. Error is thrown in demo_FHK2SOFA and converterFHK2SOFA +- demo_BTDEI2SOFA: bug fix in renamed BTDEI files +- demo_SOFA2ARI: bug fix in coordinate comparison + +*** v1.0.0 (3.6.2015) +- 'short' flag added to SOFAstart in order to show only a short header on start-up. +- warnings are function-specific now and can be specifically enabled/disabled. + +*** v0.9.1 (13.5.2015) +- 0.9.1 is the internal numbering for the release version 1.0 RC2 +- SimpleFreeFieldSOS added +- SOFAexpand and SOFAaddVariable handle Data. variables now +- SOFAplotHRTF supports SimpleFreeFielsSOS now + +*** v0.9.0 (12.5.2015) + +- 0.9.0 is the internal numbering for the release version 1.0 RC1 +- update of all conventions to SOFA 1.0 +- changes according to the AES212-standard implemented +- Octave: upgraded to a new netcdf-package: http://modb.oce.ulg.ac.be/mediawiki/index.php/Octave-netcdf +- Matlab/Octave: NETCDF* functions merged for both systems (thx to Hagen Wierstorf) +- HRTFs directory: database handling improved: + - SOFAdbPath mirrors http://sofacoustics.org/data now. + - Warning: directory structure of HRTFs/SOFA changed! + - all SOFA files created by demo_ will be saved in sofa_api_mo_test + - all demo_ files which use SOFA files will be automatically downloaded from sofacoustics.org +- clean up of comments +- SOFAcalculateAPV: reimplemented +- horsph and sph2hor: bug fixes +- directory CDL deleted (had historical relevance only) +- SOFAdefinitions: flag 'units' added for unit aliases. +- SOFAgetConventions: returns empty vector if conventions not supported + +*** v0.4.4 (until 20.4.2015) unreleased + +*** v0.4.3 (5.6.2014) by Piotr Majdak +- fix: annoying bug in SOFAupgradeConventions + +*** v0.4.2 (7.4.2014) by Piotr Majdak +- fix: SOFAhrtf2dtf supports more than two receivers + +*** v0.4.1 (30.3.2014) by Piotr Majdak +- MultiSpeakerBRIR conventions added +- SOFAcompact: compacts variables along dimensions, opposite to SOFAexpand. Functionality not complete for 3D variables +- SOFAcompare: compares two SOFA objects. Preliminary functionality; compares attributes only +- SOFAexpand: expanding of Data added +- bug fix: SOFAplotGeometry +- function-specific warnings added: SOFA:upgrade and SOFA:save +- SOFAload optimized for handling huge (3.7 GB) data files on a 4 GB RAM machine + + +*** v0.4 (19.3.2014) by Piotr Majdak +- implements SOFA 0.6: + - GLOBAL_Source renamed to GLOBAL_Origin + - GLOBAL_TimeCreated and GLOBAL_TimeModified renamed to GLOBAL_DateCreated and GLOBAL_DateModified, respectively + - If ListenerUp is provided, ListenerView must be provided as well. If ListenerView is provided, ListenerView_Type and ListenerView_Units must be provided as well. This also applies to Source, Emitter, and Receiver objects. + - Geometry: only "cartesian" or "spherical" coordinate systems allowed + - In SimpleFreeFieldHRIR: GLOBAL_SubjectID renamed to GLOBAL_ListenerShortName +- Converters adapted to provide more precise information +- SOFAappendText added for appending a text to an attribute +- SOFAdefinitions: returns various definitions, depending on the input flag +- SOFAupgradeConventions: upgrades conventions up to 0.6 now. + +*** v0.3.1 (2.9.2013) by Piotr Majdak +- zip file required 7-zip, fixed +- minor bug fixes + +*** v0.3.0 (27.8.2013) by Piotr Majdak +- major change: .API added to the structure, contains .Dimensions and the dimension sizes (formely known as .DimSize) +- implements SOFA 0.5 (without the support for string arrays) +- upgrade of SimpleFreeFieldHRIR 0.3 and other conventions +- syntax of convention files .csv adapted to that from the specs ("_" replaced by ":") +- SOFAcalculateAPV added, provides calculation of the apparent position vector (APV) +- SOFAplotGeometry added, rudimentary plotting available for SimpleFreeFieldHRIR and SingleRoomDRIR +- SOFAaddVariables supports private variables now + +*** v0.2.9 (30.5.2013) by Piotr Majdak +- development snapshot for the draft of SOFA 0.4 +- tested for Matlab (Octave support not finished yet) +- conventions implemented as CSV files which are compiled to MAT at start and are cached by SOFAgetConventions +- user-defined HRTF database path +- seemless download of remote SOFA files on SOFAload +- user-defined HRTF internet repository +- seemless upgrade from SOFA 0.3 files on SOFAload + +*** v0.2.1 (13.5.2013) by Piotr Majdak +- Bug fix with the wrong spelling of "License" +- "License" it very restrictive per default now +- demo_SOFAsave included + +*** v0.2.0 (2.5.2013) by Piotr Majdak +- Updated to SOFA 0.3 +- Octave support added +- demo_* create file names compliant with MS DOS FAT character set +- test script (test/test_SOFAall.m) added +- converters do not add database specific attriubutes, this is done in demo_* +- new demos: SOFAmerge, SOFAload, SOFAsave +- readme improved +- Pulse.sofa removed as binary, it can be created with demo_SOFAsave now +- Link to HRTF files saved as SOFA added (nice for playing around) + +*** v0.1.4 (2.5.2013) by Piotr Majdak +- Major bug fix: dimension order reversed while loading/saving in Matlab +- Some other minor issues closed +- Ready for intercompatibility test between Matlab and Octave + +*** v0.1.3 (18.4.2013) by Piotr Majdak +- This version implements SOFA specs version 0.2 with the following limitations: + - no Octave support + - only SimpleFreeFieldHRIR supported and tested + +- Detailed changes: + - directory structure changed + - new converter added: SOFA2ARI + - SOFAdbPath added + +*** v0.1.2 (17.4.2013) by Piotr Majdak +- SOFAload: partial loading added. Load of metadata only or by measurement section +- docs: changes since AES2013-specs added. +- history file moved to docs +- Repository cleaned from older stuff + +*** v0.1.1 (16.4.2013) by Piotr Majdak +- SOFAload improved: checks added. Still further checks would be nice, but it can be used now. +- SOFAsave improved: saves user-defined variables +- SOFAexpand added: expands the singleton dimensions in the SOFA object +- Convertors for MIT KEMAR, LISTEN, and CIPIC databases added (with corresponding demos) +- HRTF directory created where all HRTFs should be stored. The convertors rely on that. +- SOFAspat improved, now the engine works better + +*** v0.1.0 (11.4.2013) by Piotr Majdak +- Saving/Loading works in Matlab, it is quite rudimentary now: + - Data and Variables saved as Double + - No string in variables supported yet + - One Conventions implemented and tested (SingleFreeFieldHRIR) + - Loading: no checks (todo) + - Saving: removes optional variables (bug) + - No partial loading/saving yet +- Convertion: ARI2SOFA with demo_ARI2SOFA added +- Spatialization: very rudimentary demo added (SOFAspat and demo_SOFAspat), just for fun + +*** v0.0.12 (12.3.2013) by Piotr Majdak +- Conventions: transmitter renamed to emitter + +*** v0.0.11 (7.3.2013) by Piotr Majdak +- Conventions added +- Octave branch deleted +- Examples: ARI2SOFA as a function +- General: adapted to current specs. Don't use yet. + +*** v0.0.10 (5.3.2013) by Piotr Majdak +- ARI2SOFA: changed to a function now, the fields are more clear defined +- SOFAsave: transmitted and receiver separated, dimensions changed +- Specs have drastically changed - beware of using this version at the current development state + +*** v0.0.9 (31.1.2013) by Piotr Majdak +- included octave part from Hagen Wierstorf +- changed the data structure format +- added try-catch to SOFAsave to avoid open file handles + +*** v0.0.8 (24.08.2012) by Wolfgang Hrauda +- changed data structure format +- updates and fixes in several functions and scripts +- added Eigenmike.sofa as a demo file + +*** v0.0.7 (23.08.2012) by Wolfgang Hrauda +- now using structures or cells as input and output values of functions +- added and renamed several functions and scripts +- updates in several functions and scripts + +*** v0.0.6 (14.08.2012) by Wolfgang Hrauda +- added new functions for coordinate type conversion +- functionality of SOFAgetData slightly expanded +- dismissed function SOFAloadVariables (is now an option in SOFAload) +- "ARI_to_SOFA_lab_setup" updated +- minor fixes in several functions + +*** v0.0.5 (08.08.2012) by Wolfgang Hrauda +- implemented additional dimensions for string variables in SOFAsave +- added new function SOFAloadVariables (a variant of SOFAload) +- added new demo script "ARI_to_SOFA_lab_setup" +- fixes in several functions + +*** v0.0.4 (07.08.2012) by Wolfgang Hrauda +- fixed some issues in SOFAsave +- minor changes in SOFAload +- added new functions SOFAgetID, SOFAgetData, SOFAlistVariables + +*** v0.0.3 (03.08.2012) by Wolfgang Hrauda +- split demo script in two API functions and one script that calls them +- change file extension to 'sofa' + +*** v0.0.2 (01.08.2012) by Wolfgang Hrauda +- finished matrix dimension check + +*** v0.0.1 (31.07.2012) by Wolfgang Hrauda +- demo script that loads ARI .mat file, converts it to SOFA format and writes to .nc-file + then reads all data from .nc.file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m new file mode 100644 index 0000000000000000000000000000000000000000..cecca186bd868f8e57cdd7c8755ae5b2dfb374fc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m @@ -0,0 +1,18 @@ +function [] = NETCDFdisplay(filename) +%NETCDFDISPLAY +% [] = NETCDFdisplay(filename) displays information about specified SOFA file + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function netcdf/NETCDFdisplay +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +ncdisp(filename); + +end %of function diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m new file mode 100644 index 0000000000000000000000000000000000000000..0aa1514c1527747558416da60b1bd5b723fec213 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m @@ -0,0 +1,154 @@ +function [Obj,Dims] = NETCDFload(filename,flags,varargin) +%% NETCDFLOAD +% Obj = NETCDFload(filename,'all') reads the SOFA object OBJ with all data from a SOFA file. +% +% Obj = NETCDFload(filename,'nodata') ignores the data, reads variables. +% +% Obj = NETCDFload(filename,[START COUNT],partialDim) reads only COUNT number of data +% in dimension partialDim (given as string) beginning with the index START. If START +% and COUNT are column vectors, then partialDim has to be a string containing the +% dimension for every column entry. +% +% [Obj,Dims] = NETCDFload(...) returns the dimension variables found in +% the file as a string. + +% #Author: Piotr Majdak: String array support. Works for 1D and 2D strings only. (10.08.2014) +% #Author: Michael Mihocic: 'deblank' command added when loading strings to avoid trailing empty spaces in size of array dimension (14.10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +%% SOFA Toolbox - function netcdf/NETCDFload +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob = 'GLOBAL_'; +globid = netcdf.getConstant('GLOBAL'); + +%% --------------------------- N E T C D F load -------------------------- +% Open the NETCDF file +try + var = 'opening file'; + ncid = netcdf.open(filename,'NC_NOWRITE'); % open file + var = 'inquirying data'; + [numdims,numvars,numglob] = netcdf.inq(ncid); % get number of anything + + % ----- GLOBAL ATTRIBUTES -------------------------------------------- + for ii=0:numglob-1 + var = netcdf.inqAttName(ncid,globid,ii); + Obj.([glob var]) = netcdf.getAtt(ncid,globid,var); + end + + % ----- DIMENSIONS --------------------------------------------------- + dimids = netcdf.inqDimIDs(ncid); + dims = cell(numdims,1); % cell array with dimension names + startp = zeros(numdims,1); % vector with start of a dimension + countp = zeros(numdims,1); % vector with the element count in a dimension + for ii=0:numdims-1 + [var,len] = netcdf.inqDim(ncid,dimids(ii+1)); + Obj.API.(var) = len; + dims{ii+1} = var; + startp(ii+1) = 0; + countp(ii+1) = len; + end + Dims = cell2mat(dims)'; + + % Check the requested measurements + if isnumeric(flags) + partialDimRange = flags; + partialDim = varargin{1}; + for ii=1:length(partialDim) + if Obj.API.(partialDim(ii))<(sum(partialDimRange(ii,:))-1) + error('Requested indices exceed measurement count'); + end; + startp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,1)-1; + countp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,2); + end + end + + + % ----- VARIABLES + ATTRIBUTES --------------------------------------- + varids = netcdf.inqVarIDs(ncid); + for ii=0:numvars-1 + [var,~,vardimids,natts] = netcdf.inqVar(ncid,varids(ii+1)); + % Data + if strfind(var,'Data.'), + if ~strcmp(flags,'nodata') + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.Data.(var(6:end))=dim; + if strfind(dim,'S') % strings + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.Data.(var(6:end))=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.Data.(var(6:end))(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.Data.(var(6:end))=deblank(cellstr(reshape(reshape(data,1,[]),size(data,2),[]))); + end + elseif length(dim)>1 + Obj.Data.(var(6:end))=permute(netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)), length(dim):-1:1); + else + Obj.Data.(var(6:end))=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + end + end + % Variables + else + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.(var)=dim; + if strfind(dim,'S') + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.(var)=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.(var)(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.(var)=deblank(cellstr(reshape(reshape(data,1,[]),size(data,2),[]))); + end + elseif length(dim)>1 + Obj.(var)=permute(data, length(dim):-1:1); + else + Obj.(var)=data; + end + end + + if natts + for jj=0:natts-1 + att = netcdf.inqAttName(ncid,varids(ii+1),jj); + attval = netcdf.getAtt(ncid,varids(ii+1),att); + if strfind(var,'Data.'), Obj.Data.([var(6:end) '_' att])=attval; else Obj.([var '_' att])=attval; end + end + end + end + +catch ME + if exist('ncid','var'); netcdf.abort(ncid); end; + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message 10 'See also the error stack before']); +end + +netcdf.close(ncid); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m new file mode 100644 index 0000000000000000000000000000000000000000..7ddc4223ebdb5d2a076e89100c3c365a26f43816 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m @@ -0,0 +1,178 @@ +function NETCDFsave(filename,Obj,Compression) +%NETCDFSAVE +% NETCDFsave(filename,Dataset,Compression) saves all data and metadata to a SOFA file. + +% SOFA Toolbox - function netcdf/NETCDFsave +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% #Author: Piotr Majdak (09.04.2013) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob='GLOBAL_'; +% Dims='IRENMCQ'; % dimensions + +globid=netcdf.getConstant('GLOBAL'); + +try + var='file creation'; + mode = netcdf.getConstant('NETCDF4'); +% mode = netcdf.getConstant('clobber'); +% mode = bitor(mode,netcdf.getConstant('CLASSIC_MODEL')); + ncid = netcdf.create(filename,mode); + +%% Save global attributes + f=fieldnames(Obj); + + for ii=1:length(f) + if ~isempty(strfind(f{ii},glob)) + var=f{ii}; + netcdf.putAtt(ncid,globid,var(strfind(var,glob)+length(glob):end),Obj.(var)); + end + end + +%% Define dimensions + + Dims=cell2mat(fieldnames(rmfield(Obj.API,'Dimensions'))'); + dimid=nan(size(Dims)); + dimsize=nan(size(Dims)); + for ii=1:length(Dims) + var=Dims(ii); + dimid(ii) = netcdf.defDim(ncid,Dims(ii),Obj.API.(var)); + dimsize(ii)=Obj.API.(var); + end + Sdim=strfind(Dims,'S'); % find the index with string dimension + if isempty(Sdim), Sdim=-1, end; % mark as -1 if not existing + +%% Define metadata variables and their attributes +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varId(ii),true,true,Compression); + for jj=1:length(f) + if ~isempty(strfind(f{jj},[var '_'])) + netcdf.putAtt(ncid,varId(ii),f{jj}(strfind(f{jj},[var '_'])+length([var '_']):end),Obj.(f{jj})); + end + end + end + end + +%% Define data variables and their attributes +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varIdD(ii),true,true,Compression); + for jj=1:length(fod) + if ~isempty(strfind(fod{jj},[var '_'])) + netcdf.putAtt(ncid,varIdD(ii),fod{jj}(strfind(fod{jj},[var '_'])+length([var '_']):end),Obj.Data.(fod{jj})); + end + end + end + end + +%% End of definition + netcdf.endDef(ncid); + +%% Save metadata variables +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if length(ids)>1 + if iscell(Obj.(var)) + c=char(permute(Obj.(var),length(ids):-1:1)); + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % array 'ext' causes warnings in Octave in next row; 'strings' command would work better than 'zeros' but it is not supported in Octave + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),permute(Obj.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.(var)) + c=char(Obj.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),Obj.(var)); + end + end + end + end + +%% Save data variables +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if length(ids)>1 + if iscell(Obj.Data.(var)) + c=char(permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % array 'ext' causes warnings in Octave in next row; 'strings' command would work better than 'zeros' but it is not supported in Octave + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.Data.(var)) + c=char(Obj.Data.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),Obj.Data.(var)); + end + end + end + end + +catch ME +% if ~strcmp(ME.identifier,'MATLAB:imagesci:netcdf:libraryFailure') + netcdf.close(ncid); +% end + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message]); + +end +netcdf.close(ncid); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef64976aa6f50cc86d9e0705ccb4500a115980bf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/readme.txt @@ -0,0 +1,18 @@ +This is a readme file for the SOFA Toolbox for Matlab and Octave. + +* Add the "SOFAtoolbox" directory to Matlab search path: Use "Add Folder" (don't use "Add with Subfolders"!) +* Start the Toolbox: execute "SOFAstart" in Matlab or Octave. +* No HRTF files to play around? Follow the advices in the readme.txt files in the HRTFs directories. +* Explore the Toolbox: execute some of the "demo_" files in the directory "demos". +* Learn more about SOFA: read the specs PDF in the directory "doc". +* Report a bug: send a ticket at https://github.com/sofacoustics/SOFAtoolbox/issues. +* Last changes? check the file "history.txt". + +Tested with Matlab R2018b (and higher) and Octave 4.2.1. + +Contact the main developers: Piotr Majdak <piotr.majdak@oeaw.ac.at> and Michael Mihocic <michael.mihocic@oeaw.ac.at> + +Many thanks go to Hagen Wierstorf <hagen.wierstorf@tu-berlin.de> for the Octave support. + +Acoustics Research Insitute (ARI) +Austrian Academy of Sciences (OeAW) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m new file mode 100644 index 0000000000000000000000000000000000000000..e31f2629726e419662b6c927c38d3155c07122fa --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m @@ -0,0 +1,326 @@ +% SOFA Toolbox - test script +% Test some of the SOFA Toolbox functionality + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: missing demos added, bugs fixed (09-10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +clc; close all; % clean-up first +tic; % timer +SOFAstart; +warning('off','SOFA:upgrade'); +warning('off','SOFA:load'); +warning('off','SOFA:save'); + +%% Test converters TO SOFA +disp(' '); +disp('############################################'); +disp('####### TEST CONVERTERS TO SOFA ########'); +disp('############################################'); + +disp(' '); +disp('!!! Make sure that all source files are available in the HRTFs directories. See individual readme.txt files for more information !!!'); +disp(' '); + +%% demo_ARI2SOFA +disp('************** demo_ARI2SOFA **************'); +clear; +% subjectID='NH4'; % default +demo_ARI2SOFA +subjectID='NH2'; +demo_ARI2SOFA +disp('*** Finished: demo_ARI2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_BTDEI2SOFA +disp('************** demo_BTDEI2SOFA **************'); +clear; +demo_BTDEI2SOFA; +disp('*** Finished: demo_BTDEI2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_CIPIC2SOFA +disp('************** demo_CIPIC2SOFA **************'); +clear; +try + demo_CIPIC2SOFA; + disp('*** Finished: demo_CIPIC2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_CIPIC2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\data\CIPIC\ directory.') +end +disp(' '); + +%% demo_FHK2SOFA +clear; +% if ~exist('OCTAVE_VERSION','builtin') +disp('************** demo_FHK2SOFA **************'); +demo_FHK2SOFA; +disp('*** Finished: demo_FHK2SOFA (Output: SOFA-file(s))'); disp(' '); +% else +% disp('Skipped: demo_CIPIC2SOFA'); disp(' '); +% end + +%% demo_LISTEN2SOFA +disp('************** demo_LISTEN2SOFA **************'); +clear; +subjectID='1002'; +try + demo_LISTEN2SOFA; + disp('*** Finished: demo_LISTEN2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_LISTEN2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\data\LISTEN\ directory.') +end +disp(' '); + +%% demo_MIT2SOFA +disp('************** demo_MIT2SOFA **************'); +clear; +% pinna='normal'; % default value +demo_MIT2SOFA; +pinna='large'; +demo_MIT2SOFA; +disp('*** Finished: demo_MIT2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_SCUT2SOFA +disp('************** demo_SCUT2SOFA **************'); +clear; +try + demo_SCUT2SOFA; + disp('*** Finished: demo_SCUT2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_SCUT2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\data\SCUT\ directory.') +end +disp(' '); + +%% demo_TUBerlin2SOFA +disp('************** demo_TUBerlin2SOFA **************'); +clear; +radius=[0.5 1 2 3]; +demo_TUBerlin2SOFA; +disp('*** Finished: demo_TUBerlin2SOFA (Output: SOFA-file(s))'); disp(' '); + + +%% Test converters FROM SOFA +disp('############################################'); +disp('###### TEST CONVERTERS FROM SOFA #######'); +disp('############################################'); + +%% demo_SOFA2ARI +disp('************** demo_SOFA2ARI **************'); +clear; +demo_SOFA2ARI; +% SOFAplotGeometry(Obj); +disp('*** Finished: demo_SOFA2ARI'); disp(' '); + +%% demo_SOFAHRTF2DTF +disp('************** demo_SOFAHRTF2DTF **************'); +clear; +demo_SOFAHRTF2DTF; +disp('*** Finished: demo_SOFAHRTF2DTF (Output: Figure(s))'); disp(' '); + + +%% Test SOFA functions +disp('############################################'); +disp('###### TEST SOFA FUNCTIONS #######'); +disp('############################################'); + +%% demo_SOFAload +% Test SOFAload +disp('************** demo_SOFAload **************'); +clear; +demo_SOFAload; +disp('*** Finished: demo_SOFAload'); disp(' '); + +%% demo_SOFAmerge +% Test SOFAmerge and create TU-Berlin KEMAR file with multiple radii +disp('************** demo_SOFAmerge **************'); +clear; +demo_SOFAmerge; +disp('*** Finished: demo_SOFAmerge (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_SOFAplotGeometry +disp('************** demo_SOFAplotGeometry **************'); +clear; +demo_SOFAplotGeometry; +disp('*** Finished: demo_SOFAplotGeometry (Output: Figure(s))'); disp(' '); + +%% demo_SOFAplotHRTF +% Test plotting HRTFs +disp('************** demo_SOFAplotHRTF **************'); +demo_SOFAplotHRTF +disp('*** Finished: demo_SOFAplotHRTF (Output: Figure(s))'); disp(' '); + +% %% demo_plot_trumpet_directivity +% % Test plotting HRTFs +% disp('************** demo_plot_trumpet_directivity **************'); +% demo_plot_trumpet_directivity +% disp('*** Finished: demo_plot_trumpet_directivity (Output: Figure(s))'); disp(' '); + +%% demo_SOFAsave +disp('************** SOFAsave **************'); +clear; +demo_SOFAsave; +disp('*** Finished: SOFAsave (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAspat +% Test SOFAspat, but do not play +disp('************** demo_SOFAspat **************'); +clear; +dontplay=1; +demo_SOFAspat; +disp('*** Finished: demo_SOFAspat (Output: Figure(s))'); disp(' '); + +%% demo_SOFAstrings +% Test using string arrays +disp('************** demo_SOFAstrings **************'); +demo_SOFAstrings +disp('*** Finished: demo_SOFAstrings (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAvariables +% Test variables handling +disp('************** demo_SOFAvariables **************'); +demo_SOFAvariables +disp('*** Finished: demo_SOFAvariables (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAexpandcompact +% Test SOFAexpand and SOFAcompact +disp('************** demo_SOFAexpandcompact **************'); +clear; +demo_SOFAexpandcompact; +disp('*** Finished: demo_SOFAexpandcompact'); disp(' '); + +%% demo_SOFAcalculateITD +disp('************** demo_SOFAcalculateITD **************'); +clear; +demo_SOFAcalculateITD; +disp('*** Finished: demo_SOFAcalculateITD (Output: Figure(s))'); disp(' '); + +%% demo_SOFAcalculateLFE +disp('************** demo_SOFAcalculateLFE **************'); +clear; +demo_SOFAcalculateLFE; +disp('*** Finished: demo_SOFAcalculateLFE (Output: Figure(s))'); disp(' '); + + +%% Test SOFA conventions +disp('############################################'); +disp('###### TEST SOFA CONVENTIONS #######'); +disp('############################################'); + +%% demo_FreeFieldDirectivityTF +disp('************** demo_FreeFieldDirectivityTF **************'); +clear; +demo_FreeFieldDirectivityTF; +disp('*** Finished: demo_FreeFieldDirectivityTF (Output: Figure(s))'); disp(' '); + +%% demo_FreeFieldHRIR +disp('************** demo_FreeFieldHRIR **************'); +clear +demo_FreeFieldHRIR; +disp('*** Finished: demo_FreeFieldHRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_FreeFieldHRTF +disp('************** demo_FreeFieldHRTF **************'); +clear; +demo_FreeFieldHRTF; +disp('*** Finished: demo_FreeFieldHRTF (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_General +disp('************** demo_General **************'); +clear +demo_General; +disp('*** Finished: General (Output: SOFA-file(s))'); disp(' '); + +%% demo_GeneralFIR +disp('************** demo_GeneralFIR **************'); +clear +demo_GeneralFIR; +disp('*** Finished: demo_GeneralFIR (Output: SOFA-file(s))'); disp(' '); + +%% GeneralFIRE: outdated, use GeneralFIR-E instead + +%% demo_GeneralFIR-E +% replacing GeneralFIR +disp('************** demo_GeneralFIR_E **************'); +clear +demo_GeneralFIR_E; +disp('*** Finished: GeneralFIR_E (Output: SOFA-file(s))'); disp(' '); + +%% GeneralString: used in demo_SOFAstrings + +%% demo_GeneralTF +disp('************** demo_GeneralTF **************'); +clear +demo_GeneralTF; +disp('*** Finished: GeneralTF (Output: SOFA-file(s))'); disp(' '); + +%% demo_GeneralTF-E +disp('************** demo_GeneralTF_E **************'); +clear +demo_GeneralTF_E; +disp('*** Finished: GeneralTF-E (Output: SOFA-file(s))'); disp(' '); + +%% demo_MultiSpeakerBRIR +disp('************** demo_MultiSpeakerBRIR **************'); +clear +demo_MultiSpeakerBRIR; +disp('*** Finished: MultiSpeakerBRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleFreeFieldHRIR2TF +% Test conversions from SimpleFreeFieldHRIR to SimpleFreeFieldHRTF +disp('************** demo_SimpleFreeFieldHRIR2TF **************'); +clear; +demo_SimpleFreeFieldHRIR2TF; +disp('*** Finished: demo_SimpleFreeFieldHRIR2TF (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleFreeFieldHRSOS +disp('************** demo_SimpleFreeFieldHRSOS **************'); +clear +demo_SimpleFreeFieldHRSOS; +disp('*** Finished: SimpleFreeFieldHRSOS (Output: SOFA-file(s))'); disp(' '); + +%% SimpleFreeFieldHRTF +% used in function demo_SimpleFreeFieldHRIR2TF + +%% demo_SimpleFreeFieldSOS +disp('************** SimpleFreeFieldSOS **************'); +clear +demo_SimpleFreeFieldSOS; +disp('*** Finished: SimpleFreeFieldSOS (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleHeadphoneIR +% old name: demo_HpIR +disp('************** demo_SimpleHeadphoneIR **************'); +clear; +demo_SimpleHeadphoneIR; +disp('*** Finished: demo_SimpleHeadphoneIR (Output: Figure(s))'); disp(' '); + +%% demo_SingleRoomDRIROlcldenburg +% Test SingleRoomDRIR +disp('************** demo_SingleRoomDRIROldenburg **************'); +clear +demo_SingleRoomDRIROldenburg; +disp('*** Finished: demo_SingleRoomDRIROldenburg (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_SingleRoomMIMOSRIR +disp('************** demo_SingleRoomMIMOSRIR **************'); +clear +demo_SingleRoomMIMOSRIR; +disp('*** Finished: demo_SingleRoomMIMOSRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_SingleRoomSRIR +disp('************** SingleRoomSRIR **************'); +clear +demo_SingleRoomSRIR; +disp('*** Finished: SingleRoomSRIR (Output: SOFA-file(s))'); disp(' '); + +%% Epilogue +disp('##############################################'); +disp('#### COMPLETED ALL DEMOS SUCCESSFULLY ####'); +disp('##############################################'); +toc; % timer diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/ARI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/ARI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..c0aaf14e32a9d4ceb1688ae739a6c25805c7e813 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/ARI/readme.txt @@ -0,0 +1,7 @@ +Save here the data from the ARI database, http://www.oeaw.ac.at/isf/hrtf +Direct link to ARI database: https://projects.ari.oeaw.ac.at/research/experimental_audiology/hrtf/database/hrtfItEARI.html + +The data must be in the format as downloaded from ARI, that is NHX\hrtf_M_dtf 256.mat where NHX is the ARI subject ID. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/BTDEI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/BTDEI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba118e57056213ea47599e974a08bb1c3d1fc175 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/BTDEI/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the BT-DEI database, http://padva.dei.unipd.it/?page_id=345 +The data must be in the format as downloaded from BT-DEI, that is HXXX\SYYY\... where XXX is the headphone type and YYY the subject ID (three digits each). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/CIPIC/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/CIPIC/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..4c044289f4613a88d3e3f91a97481bda9b96ec8c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/CIPIC/readme.txt @@ -0,0 +1,7 @@ +Save here the data from the CIPIC database. +https://www.ece.ucdavis.edu/ + +The data must be in the format as downloaded from CIPIC, that is subject_XXX\hrir_final.mat where XXX is the CIPIC subject ID (three digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/FHK/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/FHK/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..1be7fba29b114ff59a967d5571c4b72d36ffaded --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/FHK/readme.txt @@ -0,0 +1,5 @@ +Save here the HRTF data from the FHK database, http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +The data must be in the format as downloaded from the server, i.e., HRIR_*.mat + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/IEM/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/IEM/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..c510933e895aba3d7880995bdf81b3a0f9299f7d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/IEM/readme.txt @@ -0,0 +1,4 @@ +Save here the 'LigetiHall_CubeletToSt450' data from the IEM database: https://phaidra.kug.ac.at/view/o:104376 + +SOFA API for Matlab and Octave +Michael Mihocic, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/LISTEN/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/LISTEN/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..83cc0f5ad0b95a934dd44d63904e440c278edbeb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/LISTEN/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the LISTEN database, http://recherche.ircam.fr/equipes/salles/listen/download.html +The data must be in the format as downloaded from IRCAM, that is IRC_XXXX\COMPENSATED\MAT\HRIR\IRC_XXX_C_HRIR.mat where XXXX is the LISTEN subject ID (4 digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/MIT KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/MIT KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..feb4a69d479a4ef84b7fea7bc5042533c31ec204 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/MIT KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the MIT database, http://sound.media.mit.edu/resources/KEMAR/full.zip +The data must be the "full" data as downloaded from MIT, that is full\elevE\PEeAa.wav where A and E is the azimuth and the elevation angles, respectively, and P is the pinna used, that is, L (normal pinna) or (large pinna). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/Oldenburg/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/Oldenburg/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..85709e35dfc0354dae14e3a203fcc41f607c73a2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/Oldenburg/readme.txt @@ -0,0 +1,6 @@ +Save here the data from the Oldeburg database, http://sirius.physik.uni-oldenburg.de/downloads/hrir/HRIR_database_mat.zip + +Note: before downloading that using that data, you must go to http://medi.uni-oldenburg.de/hrir/html/download.html and accept the form. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SCUT/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SCUT/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..a1cfbef2581b7503002efd3e57ac41d986efefc7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SCUT/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the SCUT database (Bosun Xie, Ghongzhou, China) +The data must be in the format as provided by the SCUT, e.g., the nearfield KEMAR data in the directory "nearfield". + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..7270aa38aa0f9978e68abd057e0c8fcae913d5d4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/readme.txt @@ -0,0 +1,7 @@ +SOFA files go here. + +When used with the default settings of SOFAdbURL and SOFAdbPath, this directory reflects http://www.sofacoustics.org/data/ + + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/sofatoolbox_test/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/sofatoolbox_test/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..458ab5cc8fb3332208879a114c34cc4a7754e885 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/SOFA/sofatoolbox_test/readme.txt @@ -0,0 +1,8 @@ +SOFA files go here. They can be + +* manually downloaded by you from http://tinyurl.com/sofaHRTFs +* automatically created by the Toolbox by demo_ functions when the source HRTFs are available +* automatically downloaded by the Toolbox from http://www.sofacoustics.org/data/sofatoolbox_test when requested and available + +SOFA Toolbox for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/TU-Berlin KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/TU-Berlin KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..f80db755519a8b4da271e7c23edef97010027dcd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/data/TU-Berlin KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the TU-Berlin database, https://doi.org/10.5281/zenodo.4459911 +The data must be in the format as downloaded from TU Berlin. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO 1.0.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO 1.0.fodt new file mode 100644 index 0000000000000000000000000000000000000000..8501cc62e07c124f2ea3aed23324efd71d20015c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO 1.0.fodt @@ -0,0 +1,1280 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 1.0</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>247</meta:editing-cycles><meta:editing-duration>P2DT12H58S</meta:editing-duration><meta:generator>LibreOffice/6.2.4.2$Windows_X86_64 LibreOffice_project/2412653d852ce75f65fbfa83fb7e7b669a126d64</meta:generator><dc:date>2019-07-30T11:18:40.946000000</dc:date><dc:creator>Piotr Majdak</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="35" meta:word-count="431" meta:character-count="2885" meta:non-whitespace-character-count="2506"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">28737</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">17969</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">13183</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">1820</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">28736</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">17967</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">13923478</config:config-item> + <config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Mangal1" svg:font-family="Mangal"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Zeichenformat" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial1"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial1"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00d41fec" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T19" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T20" style:family="text"> + <style:text-properties officeooo:rsid="00d41fec"/> + </style:style> + <style:style style:name="T21" style:family="text"> + <style:text-properties officeooo:rsid="00d47496"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L3"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">Matlab/Octave API for SOFA </text:span><text:title>version 1.0</text:title><text:tab/><text:span text:style-name="T2"><text:tab/>Page: </text:span><text:span text:style-name="T2"><text:page-number text:select-page="current">1</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P29">Matlab/Octave API for SOFA</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T10">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T6">Acoustics Research Institute </text:span><text:span text:style-name="T9">(ARI)</text:span><text:span text:style-name="T6">, <text:line-break/>Austrian Academy of Sciences </text:span><text:span text:style-name="T9">(OeAW)</text:span><text:span text:style-name="T6"><text:line-break/></text:span><text:span text:style-name="T7">Vienna</text:span><text:span text:style-name="T6">, Austria</text:span><text:span text:style-name="T10"><text:line-break/></text:span><text:span text:style-name="T8"><</text:span><text:span text:style-name="T5">piotr@majdak.com</text:span><text:span text:style-name="T8">></text:span></text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T16">This document contains preliminary remarks on the <text:line-break/>API_MO </text:span><text:span text:style-name="T16"><text:title>version 1.0</text:title></text:span><text:span text:style-name="T16">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T17">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list2795606257" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P30"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P40"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T10">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P30"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T15">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T15">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P31"><text:span text:style-name="Strong_20_Emphasis">Wolfgang Hrauda </text:span><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T5">wolfgang.hrauda@gmx.at</text:span></text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P32" text:outline-level="2"/> + <text:h text:style-name="P7" text:outline-level="1">STARTING the API</text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T19">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the API.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt <text:span text:style-name="T20">or help SOFAstart.</text:span></text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the API are provided. This is the first place to get familiar with the structure of the API.</text:p> + <text:p text:style-name="P23">Note that for the demonstration of conversion functions, you will most probably need to download some non-SOFA HRTF files first. See readme.txt files in the HRTF directories of the corresponding non-SOFA format.</text:p> + <text:h text:style-name="P6" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P16">All the SOFA information is stored in the a variable which we call SOFA object here. <text:span text:style-name="T20">Such an object is, for example, returned by the function SOFAload. </text:span>In that object:</text:p> + <text:list xml:id="list1306107549" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P33">“GLOBAL_” <text:span text:style-name="T20">are all g</text:span>lobal attributes. <text:span text:style-name="T21">Use prefix GLOBAL_ to add your global attributes.</text:span> </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P36">Variables are stored with their names as they are.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="T20">An a</text:span>ttribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P34">“Data.” <text:span text:style-name="T20">is a </text:span>separate structure <text:span text:style-name="T20">containing </text:span>the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33">“PRIVATE” <text:span text:style-name="T20">is a</text:span> structure with private data for application use. <text:span text:style-name="T20">Here you can store your private variables which belong to the SOFA object. P</text:span>rivate <text:span text:style-name="T20">variables</text:span> won't be saved when saving <text:span text:style-name="T20">the</text:span> object <text:span text:style-name="T20">as a SOFA file.</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35">“API” <text:span text:style-name="T20">contains </text:span>internal variables <text:span text:style-name="T20">of the API. Do not modify them, use SOFAupdateDimensions() to update them according to your data. These variables</text:span> are <text:span text:style-name="T21">useful for handling the SOFA data</text:span>:</text:p> + <text:list> + <text:list-item> + <text:p text:style-name="P35">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">Use SOFAaddVariable() to add a new variable. </text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P17">Further resources can be found:</text:p> + <text:list xml:id="list2018448349" text:style-name="L3"> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T20">API_MO</text:span>/readme.txt provides a short description of the API.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T20">API_MO</text:span>/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">doc/specs provides specifications of the currently supported SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/SOFA stores SOFA files. Per default, it mirrors http://sofacoustics.org/data.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/SOFA/sofa_api_mo_test: here, the automatically created SOFA files will be saved for testing purposes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/other directories: directories containing HRTF files stored in other formats than SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">http://sofaconventions.org provides the most recent information on SOFA.</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt new file mode 100644 index 0000000000000000000000000000000000000000..63ebe4d9a21843cd82c9280b34b99372606617a0 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt @@ -0,0 +1,1248 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 0.4</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>234</meta:editing-cycles><meta:editing-duration>P2DT11H41M48S</meta:editing-duration><meta:generator>LibreOffice/4.2.1.1$Windows_x86 LibreOffice_project/d7dbbd7842e6a58b0f521599204e827654e1fb8b</meta:generator><dc:date>2014-03-20T17:53:51.716000000</dc:date><dc:creator>Piotr Majdak</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="28" meta:word-count="272" meta:character-count="1831" meta:non-whitespace-character-count="1599"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="int">34555</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="int">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="int">26169</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="int">21063</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="int">15688</config:config-item> + <config:config-item config:name="ViewTop" config:type="int">37447</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="int">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="int">34555</config:config-item> + <config:config-item config:name="VisibleRight" config:type="int">26167</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="int">55615</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">13612822</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Mangal1" svg:font-family="Mangal"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L4"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:list-style-name="L1"/> + <style:style style:name="P26" style:family="paragraph" style:list-style-name="L2"/> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L3"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L4"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:layout-grid-snap-to-characters="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:layout-grid-snap-to-characters="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">Matlab and Octave API for SOFA </text:span><text:title>version 0.4</text:title><text:tab/><text:span text:style-name="T2"><text:tab/>Page: </text:span><text:span text:style-name="T2"><text:page-number text:select-page="current">2</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P29">Matlab and Octave API for SOFA</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T9">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T6">Acoustics Research Institute, Austrian Academy of Sciences, </text:span><text:span text:style-name="T7">Vienna</text:span><text:span text:style-name="T6">, Austria</text:span><text:span text:style-name="T9"><text:line-break/></text:span><text:span text:style-name="T8"><</text:span><text:span text:style-name="T5">piotr@majdak.com</text:span><text:span text:style-name="T8">></text:span></text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T15">This document contains preliminary remarks on the <text:line-break/>API_MO </text:span><text:span text:style-name="T15"><text:title>version 0.4</text:title></text:span><text:span text:style-name="T15">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T16">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list6831239085214927904" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P17"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P24"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T9">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P17"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T14">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T14">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P18" text:outline-level="2"/> + <text:h text:style-name="P28" text:outline-level="1">STARTING the API</text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T18">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the API.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt.</text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the API are provided. This is the first place to get familiar with the structure of the API.</text:p> + <text:h text:style-name="P27" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P23">All the SOFA information is stored in the a variable which we call SOFA object here. In that object:</text:p> + <text:list xml:id="list382891697804604485" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P19">“Data.”: separate structure with the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">“GLOBAL_”: Global attributes </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">Attribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">“PRIVATE”: structure with private data for application use. Private data won't be saved when saving a SOFA object. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">API internal variables are:</text:p> + </text:list-item> + </text:list> + <text:list xml:id="list7731056547229950280" text:style-name="L4"> + <text:list-item> + <text:p text:style-name="P22">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P22">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P20">Further resources can be found:</text:p> + <text:list xml:id="list1373325075875023343" text:style-name="L3"> + <text:list-item> + <text:p text:style-name="P21">api_mo/readme.txt provides a short description of the API.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">api_mo/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">doc/specs provides specifications of the currently supported SOFA</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">http://sofaconventions.org provides the most recent information on SOFA</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/Conventions2Wiki.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/Conventions2Wiki.m new file mode 100644 index 0000000000000000000000000000000000000000..36d1c1bed5a615c7c4e83b2cdb8387705d34dced --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/Conventions2Wiki.m @@ -0,0 +1,36 @@ +%% Convert all convention files to Wiki tables + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated, license text added (28.10.2021) + +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +p=fullfile('..','SOFAtoolbox','conventions'); +d=dir([p filesep '*.csv']); +conventions={}; +for ii=1:length(d) + dn=d(ii).name; + conventions{ii}=dn(1:end-4); +end + +for jj=1:length(conventions) + fid=fopen([p filesep conventions{jj} '.csv']); + C=textscan(fid,'%s%s%s%s%s%s','Delimiter','\t','Headerlines',1); + fclose(fid); + fid=fopen([conventions{jj} '.txt'],'w'); + fprintf(fid,'{| border="1"\n!Name\n!Default\n![[SOFA_conventions#AnchorFlags|Flags]]\n![[SOFA_conventions#AnchorDimensions|Dimensions]]\n!Type\n!Comment\n'); +% C2=regexprep(C{2},'''', '’'); % replace single quota (') by ′ + for ii=1:length(C{1}) + fprintf(fid,['|-\n|' C{1}{ii} '||<nowiki>' C{2}{ii} '</nowiki>||' C{3}{ii} '||' C{4}{ii} '||' C{5}{ii} '||' C{6}{ii} '\n']); + end + fprintf(fid,'|}'); + fclose(fid); +end +disp (' ** done **'); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/Toolbox 2.0.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/Toolbox 2.0.fodt new file mode 100644 index 0000000000000000000000000000000000000000..4afadfdb8e9f077972c747328dad97521cb85dd1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/doc/Toolbox 2.0.fodt @@ -0,0 +1,1277 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:officeooo="http://openoffice.org/2009/office" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 2.0</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>250</meta:editing-cycles><meta:editing-duration>P2DT12H5M37S</meta:editing-duration><meta:generator>LibreOffice/7.3.4.2$Windows_X86_64 LibreOffice_project/728fec16bd5f605073805c3c9e7c4212a0120dc5</meta:generator><dc:date>2022-07-28T13:12:29.231000000</dc:date><dc:creator>Michael Mihocic</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="36" meta:word-count="436" meta:character-count="2961" meta:non-whitespace-character-count="2578"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">38022</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">18840</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">21701</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">9500</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">38021</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">18838</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">14009041</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item> + <config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item> + <config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item> + <config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal"/> + <style:font-face style:name="Mangal1" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"> + <style:tab-stops> + <style:tab-stop style:position="8.5cm" style:type="center"/> + <style:tab-stop style:position="17cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Index_20_Heading" style:display-name="Index Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" loext:opacity="100%" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Zeichenformat" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" loext:num-list-format="%1%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" loext:num-list-format="%1%.%2%." style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" loext:num-list-format="%1%.%2%.%3%." style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" loext:num-list-format="%1%.%2%.%3%.%4%." style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" loext:num-list-format="%1%.%2%.%3%.%4%.%5%." style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" loext:num-list-format="%2%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" loext:num-list-format="%3%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" loext:num-list-format="%5%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" loext:num-list-format="%6%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" loext:num-list-format="%8%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" loext:num-list-format="%9%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" loext:num-list-format="%1%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" loext:num-list-format="%2%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" loext:num-list-format="%3%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" loext:num-list-format="%4%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" loext:num-list-format="%5%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" loext:num-list-format="%6%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" loext:num-list-format="%7%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" loext:num-list-format="%8%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" loext:num-list-format="%9%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" loext:num-list-format="%10%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" loext:num-list-format="%1%." style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" loext:num-list-format="%2%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" loext:num-list-format="%3%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" loext:num-list-format="%4%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" loext:num-list-format="%5%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" loext:num-list-format="%6%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" loext:num-list-format="%7%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" loext:num-list-format="%8%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" loext:num-list-format="%9%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" loext:num-list-format="%1%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" loext:num-list-format="%1%.%2%." style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" loext:num-list-format="%1%.%2%.%3%." style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" loext:num-list-format="%1%.%2%.%3%.%4%." style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" loext:num-list-format="%1%.%2%.%3%.%4%.%5%." style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" loext:num-list-format="%6%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" loext:num-list-format="%7%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" loext:num-list-format="%8%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" loext:num-list-format="%9%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" loext:num-list-format="%1%." style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" loext:num-list-format="%2%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" loext:num-list-format="%3%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" loext:num-list-format="%4%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" loext:num-list-format="%5%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" loext:num-list-format="%6%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" loext:num-list-format="%7%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" loext:num-list-format="%8%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" loext:num-list-format="%9%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" loext:num-list-format="[%1%]" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" loext:num-list-format="%2%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" loext:num-list-format="%3%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" loext:num-list-format="%4%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" loext:num-list-format="%5%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" loext:num-list-format="%6%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" loext:num-list-format="%7%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" loext:num-list-format="%8%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" loext:num-list-format="%9%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Subtitle"> + <style:paragraph-properties style:writing-mode="lr-tb"/> + <style:text-properties officeooo:rsid="00d5c2d1" officeooo:paragraph-rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Subtitle"> + <style:paragraph-properties style:writing-mode="lr-tb"/> + </style:style> + <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P41" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P42" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P43" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P44" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto" style:writing-mode="lr-tb"/> + <style:text-properties officeooo:rsid="00cbc3ea" officeooo:paragraph-rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00d41fec" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T19" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T20" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T21" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T22" style:family="text"> + <style:text-properties officeooo:rsid="00d41fec"/> + </style:style> + <style:style style:name="T23" style:family="text"> + <style:text-properties officeooo:rsid="00d47496"/> + </style:style> + <style:style style:name="T24" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" loext:num-list-format="%2%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" loext:num-list-format="%3%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" loext:num-list-format="%5%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" loext:num-list-format="%6%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" loext:num-list-format="%8%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" loext:num-list-format="%9%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" loext:num-list-format="%2%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" loext:num-list-format="%3%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" loext:num-list-format="%5%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" loext:num-list-format="%6%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" loext:num-list-format="%8%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" loext:num-list-format="%9%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"> + <style:drawing-page-properties draw:background-size="full"/> + </style:style> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">SOFA Toolbox for Matlab/Octave</text:span><text:span text:style-name="T2"> </text:span><text:title>version 2.0</text:title><text:tab/><text:span text:style-name="T3"><text:tab/>Page: </text:span><text:span text:style-name="T3"><text:page-number text:select-page="current">2</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" draw:style-name="dp1" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3" draw:style-name="dp1"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4" draw:style-name="dp1"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4" draw:style-name="dp1"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P44">SOFA <text:span text:style-name="T24">Toolbox for </text:span>Matlab/Octave</text:p> + <text:p text:style-name="P31">(previously SOFA API_MO)</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T12">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T8">Acoustics Research Institute </text:span><text:span text:style-name="T11">(ARI)</text:span><text:span text:style-name="T8">, <text:line-break/>Austrian Academy of Sciences </text:span><text:span text:style-name="T11">(OeAW)</text:span><text:span text:style-name="T8"><text:line-break/></text:span><text:span text:style-name="T9">Vienna</text:span><text:span text:style-name="T8">, Austria</text:span><text:span text:style-name="T12"><text:line-break/></text:span><text:span text:style-name="T10"><</text:span><text:span text:style-name="T7">piotr@majdak.com</text:span><text:span text:style-name="T10">></text:span></text:p> + <text:p text:style-name="P32"><text:span text:style-name="T18">This document contains preliminary remarks on the <text:line-break/></text:span><text:span text:style-name="T24">SOFA Toolbox</text:span><text:span text:style-name="T18"> </text:span><text:span text:style-name="T18"><text:title>version 2.0</text:title></text:span><text:span text:style-name="T18">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T19">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list301348430" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P34"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T12">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T17">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T17">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35"><text:span text:style-name="Strong_20_Emphasis">Wolfgang Hrauda </text:span><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T7">wolfgang.hrauda@gmx.at</text:span></text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P36" text:outline-level="2"/> + <text:h text:style-name="P11" text:outline-level="1">STARTING the <text:span text:style-name="T24">Toolbox</text:span></text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T21">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the <text:span text:style-name="T24">Toolbox</text:span>.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt <text:span text:style-name="T22">or help SOFAstart.</text:span></text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the Toolbox are provided. This is the first place to get familiar with the structure of the Toolbox.</text:p> + <text:p text:style-name="P24">Note that for the demonstration of conversion functions, you will most probably need to download some non-SOFA HRTF files first. See readme.txt files in the HRTF directories of the corresponding non-SOFA format.</text:p> + <text:h text:style-name="P9" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P10">All the SOFA information is stored in the a variable which we call SOFA object here. <text:span text:style-name="T22">Such an object is, for example, returned by the function SOFAload. </text:span>In that object:</text:p> + <text:list xml:id="list2273856870" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P37">“GLOBAL_” <text:span text:style-name="T22">are all g</text:span>lobal attributes. <text:span text:style-name="T23">Use prefix GLOBAL_ to add your global attributes.</text:span> </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P40">Variables are stored with their names as they are.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T22">An a</text:span>ttribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">“Data.” <text:span text:style-name="T22">is a </text:span>separate structure <text:span text:style-name="T22">containing </text:span>the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">“PRIVATE” <text:span text:style-name="T22">is a</text:span> structure with private data for application use. <text:span text:style-name="T22">Here you can store your private variables which belong to the SOFA object. P</text:span>rivate <text:span text:style-name="T22">variables</text:span> won't be saved when saving <text:span text:style-name="T22">the</text:span> object <text:span text:style-name="T22">as a SOFA file.</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">“API” <text:span text:style-name="T22">contains </text:span>internal variables <text:span text:style-name="T22">of the </text:span><text:span text:style-name="T24">Toolbox </text:span><text:span text:style-name="T22">API. Do not modify them, use SOFAupdateDimensions() to update them according to your data. These variables</text:span> are <text:span text:style-name="T23">useful for handling the SOFA data</text:span>:</text:p> + <text:list> + <text:list-item> + <text:p text:style-name="P39">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + </text:list-item> + <text:list-item> + <text:p text:style-name="P41">Use SOFAaddVariable() to add a new variable. </text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P18">Further resources can be found:</text:p> + <text:list xml:id="list3009974912" text:style-name="L2"> + <text:list-item> + <text:p text:style-name="P42">SOFAtoolbox/readme.txt provides a short description of the SOFAtoolbox.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">SOFAtoolbox/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">doc/specs provides specifications of the currently supported SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/SOFA stores SOFA files. Per default, it mirrors http://sofacoustics.org/data.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/SOFA/sofa<text:span text:style-name="T24">toolbox</text:span>_test: here, the automatically created SOFA files will be saved for testing purposes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/other directories: directories containing HRTF files stored in other formats than SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">http://sofaconventions.org provides the most recent information on SOFA.</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/license.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..355bc6cdd47000634dc919a2f65235c850219a88 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/deps/SOFA_API/SOFAtoolbox-master/license.txt @@ -0,0 +1,287 @@ +EUROPEAN UNION PUBLIC LICENCE v. 1.2 +EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + + Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +1. Definitions + +In this Licence, the following terms have the following meaning: + +- ‘The Licence’: this Licence. + +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. + +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. + +- ‘The Work’: the Original Work or its Derivative Works. + +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. + +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. + +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. + +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. + +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. + +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/release-notes.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/release-notes.md new file mode 100644 index 0000000000000000000000000000000000000000..4ad8c2420391ff97819998ebcd36f9a026f21d5e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/MatlabToolbox-master/release-notes.md @@ -0,0 +1,77 @@ +# v2.8 - 17th June 2017 + +- Added kernelDensity function. +- boxPlot: Added ‘violin’ methods and properties for making violin plots. +- boxPlot: Added various violin-related options. Also modified the scatter offset to use kernel density rather than histogram. +- boxPlot: Added themeColor property, allowing the various colours for the theme to be changed via a single property. +- calcSnr: Prevent rank deficient warning when output is zeros. + +# v2.7 - 28th March 2017 + +- Added true functional boxplot. +- Added alternative perceptual centroid function. +- Added caching of various dependent properties to iosr.bss.mixture class. +- Added identifiers to all warnings and errors. +- Updated loudness weighting calculations for A and C to better match IEC 61672. Added normalisation ISO 226 curve at 1kHz to bring it in to line with other weighting functions. +- Improved extrapolation of ISO 226 function. Added params output to return reference values. +- Updated SOFA API version in installer. +- Bug fixes and documentation improvements. + +# v2.6 - 6th March 2017 + +Added a number of properties and methods to the iosr.bss.mixture class. Added whiskers property to iosr.statistics.functionalSpreadPlot. Other minor bug fixes and documentation improvements. + +# v2.5 - 20th February 2017 + +Generalised iosr.bss.mixture class to support arbitrary spatial configurations, as well as none. Added decomposition properties to allow direct calculation of ideal masks, and application of masks. Currently, only STFT is supported; will add gammatone in due course. Added a number of of measures related to the mask and to signal overlap. + +A few bug fixes. + +# v2.4.1 - 18th January 2017 + +Added optional first argument to boxPlot and functionalSpreadPlot to specify axes in which to plot. + +# v2.4 - 15th December 2016 + +Added functionalSpreadPlot for making functional box plots and related plots. Also added statsPlot class and moved some boxPlot methods to the class, as they are shared with functionalSpreadPlot. + +# v2.3.2 - 13th October 2016 + +* Added check for OCTAVE in irStats, and a basic check for a unique peak. +* Corrected mistake in boxPlot documentation (pulled from TGabor). +* Moved important bits of documentation into chXcorr.m (the only separately-documented portion of the code). + +# v2.3.1 - 25th July 2016 + +* Minor tweak to magnitude calculation in matchEQ. +* Redefined TIR in mixture class as target w.r.t. sum of interfering sources. Updated documentation. + +# v2.3 - 19th July 2016 + +* Corrected code to restore current directory when installation is complete. +* Added function to generate BSS mixtures by combining sources in various ways. +* Added property to iosr.bss.mixture to return interferer filenames as char array. Also corrected bug setting properties when interferer comprises multiple sources. + +# v2.2.3 - 12th July 2016 + +Corrected boxPlot bug whereby x-separator line would disappear when setting y-axis limits to inf. + +# v2.2.2 - 10th July 2016 + +Corrected calls to other toolbox functions. + +# v2.2.1 - 8th July 2016 + +Fixed erroneous default 'method' in boxPlot. + +# v2.2 - 7th July 2016 + +Added install function that downloads dependencies and sets path. Fixed bug in boxPlot where some set functions check the old value rather than the new value. + +# v2.1 - 22nd June 2016 + +Added match EQ function. + +# v2 - 6th June 2016 + +Restructured toolbox into a Matlab package in order to appropriately restrict namespace. Consolidated some file/function names into a consistent format. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Peaks_2D.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Peaks_2D.m new file mode 100644 index 0000000000000000000000000000000000000000..fe03276c4ab64e40afa3a469020ce5f1426a11f5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Peaks_2D.m @@ -0,0 +1,54 @@ +addpath RIRs\ + +[kit, fs] = audioread('Kitchen_BFormat.wav'); +hW = kit(:,1).'; hX = kit(:,2).'; hY = kit(:,3).'; hZ = kit(:,4).'; + +T = length (kit); +T2= 48; % 10 ms or 0.01 s +t = (1:T2)/fs; + +theta = (0:5:90)*pi/180; % The azimuth 0 < theta < 2pi +phi = (0:5:90)*pi/180; % The elevation -pi/2 < phi < pi/2 + +Theta = repmat(permute(theta,[2,1]),[1, size(phi,2), T2]); +Phi = repmat(phi, [size(theta,2), 1, T2]); +ttime = repmat(permute(t, [1,3,2]), [size(theta,2), size(phi,2),1]); +% phi = 0; + +d= 1; +rx = d*(cos(theta).')*cos(phi); +ry = d*(sin(theta).')*cos(phi); +rz = d*sin(phi); + +hx = permute(hX(1:T2),[1,3,2]); hy = permute(hY(1:T2),[1,3,2]); +hz = permute(hZ(1:T2),[1,3,2]); +hx = repmat(hx,[size(theta,2),size(phi,2),1]); +hy = repmat(hy,[size(theta,2),size(phi,2),1]); +hz = repmat(hz,[size(theta,2),size(phi,2),1]); + +% Srt = 0.5*(hW + rx*hX + ry*hY); +% Srt = 0.5*(rx*hX + ry*hY); +% Srt_comp = Srt .*(10.^((6/20)*log2(t))); +Rx = repmat(rx,[1,1,T2]); Ry = repmat(ry,[1,1,T2]); +Rz = repmat(rz,[1,1,T2]); +Srt_3D = 0.5*(Rx.*hx + Ry.*hy + Rz.*hz); +comp = (10.^(-(6/20)*log2(t))); % To compensate for the drop of energy +bias = repmat(permute(comp, [1,3,2]),[size(theta,2),size(phi,2),1]); +Srt_comp = randn(size(theta,2),size(phi,2),T2); %Srt_comp = Srt_3D .* bias; +% figure; imagesc(theta, phi, rx, [-1 1]); +% figure; imagesc(theta, phi, ry, [0 1]); + +figure; scatter3(Theta(:),Phi(:),ttime(:),abs(Srt_comp(:)),'filled'); +%% + +figure; imagesc( (1:T2)/fs, (theta)*180/pi, Srt(:,1:T2),[0 0.1]); +xlabel ('time [s]'); ylabel ('\theta [degree]') + +figure; imagesc( (1:T2)/fs, (theta)*180/pi, Srt_comp(:,1:T2),[0 0.001]); +xlabel ('time [s]'); ylabel ('\theta [degree]') + +figure; imagesc( (1:T2)/fs, (theta)*180/pi, -log10(Srt(:,1:T2).^2),[0 10]); +xlabel ('time [s]'); ylabel ('\theta [degree]') + +figure; h = imagesc( (1:T2)/fs, (theta)*180/pi, 1000.*(Srt(:,1:T2)),[0 500]); +xlabel ('time [s]'); ylabel ('\theta [degree]') \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/RIRs_plot.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/RIRs_plot.m new file mode 100644 index 0000000000000000000000000000000000000000..0bbbbb964ec0ee4df2830faf0d4884da86cc0f50 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/RIRs_plot.m @@ -0,0 +1,21 @@ +% Script files to plot the RIRs of the rooms in time domain + +cd RIRs\ + +WavFiles =dir('*.wav'); +N = length(WavFiles); + +for i = 1:N +Filename = WavFiles(i).name; +[rir, fs] = audioread(Filename); +t = (1:length(rir))/fs; +% Let's check the RIR up to t=0.3 second (to zoom) +% zoom = 1*fs; +zoom = 0.3*fs; +figure; plot(t(1:zoom),rir(1:zoom,1)); +%figure; plot(t,rir(:,1)); +title(['RIR of ' Filename(1:end-12)]) +xlabel('t [s]') +end + +cd .. \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef45c32b5de791f7930edbef602225f39f766c9e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/Readme.txt @@ -0,0 +1,8 @@ + + +% To evaluate the metrics using irStats function in IoSR Toolbox use the m file +Matlab files/IoSR Toolbox/+iosr/+acoustics/irStats.m +[RT, DRR, C50, Cfc, EDT] = iosr.acoustics.irStats('rir_record.wav','spec', 'full'); +% Notice that RT & EDT outputs with 'spec' : 'mean' (defult) are the mean of the 500 Hz & 1 kHz bands. +% With 'spec': 'full', the function returns the RT & EDT as calculated for each octave band in Cfc, we chose to average the results over 6 octave bands (3:8) + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/ResultsforMethods.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/ResultsforMethods.m new file mode 100644 index 0000000000000000000000000000000000000000..073da12d8a8f59572683af1a912b660f51468eb4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/ResultsforMethods.m @@ -0,0 +1,82 @@ + % Script file to plot and evaluate the performance of the algorithms for + % different rooms + + addpath RIRs + addpath Unity-ogg-files\ + addpath 'RIRs' 'IoSR Toolbox' 'octave' + + Rooms = {'BBC_LR', 'BBC_UL', 'Courtyard', 'DWRC', 'Kitchen', 'Studio1'}; + Methods = {'recorded', 'sirr', 'rsao_SigTmix', 'combined'}; + earlyt_vec = [ 0.01, 0.01, 0.08, 0.03, 0.04, 0.01]; + % This is the early part of RIR chosen to calculate the correlation between + % the recorded and regenerated RIRs. This is different for each room. + tlen_vec = [0.1, 0.1, 0.5, 0.2, 0.3, 0.1] ; + % Since the whole recorded RIR is too long and almost zero after a short + % time we only choose the length containing energy. This is different for + % each room + + Nr = length(Rooms); % Number of Rooms + Nmethods = length(Methods); % Number of methods including the ground truth + Octave_bands = 9; + Nmetric = 4; + + for r = 3:5 %1:Nr + + earlyt = earlyt_vec(r); tlen = tlen_vec(r); + % Determining the size of metrics + RT = zeros(Octave_bands,Nmethods); EDT = zeros(Octave_bands,Nmethods); + DRR = zeros(Octave_bands,Nmethods); C50 = zeros(Octave_bands,Nmethods); + Cfs = zeros(Nmethods, Octave_bands); + + room_name = cell2mat(Rooms(r)); + [rir_gt, fs] = audioread([room_name '_BFormat.wav']); + assignin('base', [room_name '_recorded'], rir_gt(:,1)); + + audiowrite('rir_record.wav',rir_gt(:,1)./2,fs); + % To evaluate the metrics using irStats function in IoSR Toolbox + % Matlab files/IoSR Toolbox/+iosr/+acoustics/irStats.m + [RT(:,1), DRR(:,1), C50(:,1), Cfs(1,:), EDT(:,1)] = ... + iosr.acoustics.irStats('rir_record.wav','spec', 'full'); + + result = eval(['plot(' [room_name '_recorded'] ');']); + xlabel ({'Time [s]'},'FontSize',12); + ylim([-1 1]); + xlabel ({'Time [s]'},'FontSize',12); + ylabel({'Amplitude'},'FontSize',12); + title('Original RIR','FontSize',12); + clear rir_gt + + + + for m = 2:Nmethods % Starts from the 2nd as the ground truth (recorded) + % signal is already evaluated + method_name = cell2mat(Methods(m)); + [rir, fs] = audioread([room_name '_' method_name '_rir.ogg']); + assignin('base', [room_name '_' method_name], rir(:,1)./max(rir(:,1))); + + audiowrite('rir_regenerate.wav',rir(:,1)./2,fs); + [RT(:,m), DRR(:,m), C50(:,m), Cfs(m,:), EDT(:,m)] = ... + iosr.acoustics.irStats('rir_regenerate.wav','spec', 'full'); + % iosr.acoustics.irStats('rir_record.wav','graph', true, 'spec', 'full'); + % To plot the EDT & RT60 curves in octave bands + + + figure; gt_plot = eval(['plot(' [room_name '_recorded'] ');']); + hold on; method_plot = eval(['plot(' [room_name '_' method_name] ');']); + xlabel ({'Time [s]'},'FontSize',12); + ylim([-1 1]); grid on; + xlabel ({'Time [s]'},'FontSize',12); + ylabel({'Amplitude'},'FontSize',12); + title([room_name '-' method_name],'FontSize',12); + + end + + Results = [RT, DRR, C50, EDT]; + Full_freq = reshape(Results,[Octave_bands,Nmethods,Nmetric]); + % Tensor Matrix of size N_Octave_bands x Nmethods x Nmetrics + assignin('base', [room_name '_full_freq_results'], Full_freq); + mean_results = squeeze(mean(Full_freq,1)); + % Matrix of size Nmethods x Nmetrics + assignin('base', [room_name '_avrg_results'], mean_results); + + end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA API for Matlab and Octave 1.1.3.zip b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA API for Matlab and Octave 1.1.3.zip new file mode 100644 index 0000000000000000000000000000000000000000..1f081057f69c0115a97ad55429a29b0e8f998ccb Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA API for Matlab and Octave 1.1.3.zip differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/Ati_SOFA_load.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/Ati_SOFA_load.m new file mode 100644 index 0000000000000000000000000000000000000000..a580396d3642bd1f819324c3dd473aae3e1549a3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/Ati_SOFA_load.m @@ -0,0 +1,29 @@ +%% put your information here: +addpath SOFA_API_Matlab_Octave/API_MO +addpath SOFA_API_Matlab_Octave/API_MO/netcdf +addpath SOFA_API_Matlab_Octave/API_MO/conventions +% addpath SOFAtoolbox-master/SOFAtoolbox/converters +rir = SOFAload('BBC-LR-UCA-HK.sofa'); +% rir = SOFAload('DWRC-UCA-HK.sofa'); +% rir = SOFAload('BBC-UL-UCA-HK.sofa'); +% rir = SOFAload('OfficeII.sofa'); +soundInput = audioread('Man Speech.wav'); +ListeningRoom_rir = audioread('BBC_LR_BFormat.wav'); + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(rir); +% Plot a figure with the measurement setup +SOFAplotGeometry(rir); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(rir.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(rir); +% Listen to the rir with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(rir, 91); +soundOutput = [conv(squeeze(rir.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(rir.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, rir.Data.SamplingRate); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-LR-UCA-HK.sofa b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-LR-UCA-HK.sofa new file mode 100644 index 0000000000000000000000000000000000000000..556091c5dfe9e31611e348db6b504e11bfc8e3ac Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-LR-UCA-HK.sofa differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-LR-UCA.sofa b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-LR-UCA.sofa new file mode 100644 index 0000000000000000000000000000000000000000..556091c5dfe9e31611e348db6b504e11bfc8e3ac Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-LR-UCA.sofa differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-UL-UCA-HK.sofa b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-UL-UCA-HK.sofa new file mode 100644 index 0000000000000000000000000000000000000000..5cff3a1dddb6f94025f03614284e667d17db8711 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-UL-UCA-HK.sofa differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-UL-UCA.sofa b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-UL-UCA.sofa new file mode 100644 index 0000000000000000000000000000000000000000..5cff3a1dddb6f94025f03614284e667d17db8711 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/BBC-UL-UCA.sofa differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/DWRC-UCA-HK.sofa b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/DWRC-UCA-HK.sofa new file mode 100644 index 0000000000000000000000000000000000000000..00fdd4345abc615d3be760c87d6e42052603fdb1 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/DWRC-UCA-HK.sofa differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/DWRC-UCA.sofa b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/DWRC-UCA.sofa new file mode 100644 index 0000000000000000000000000000000000000000..00fdd4345abc615d3be760c87d6e42052603fdb1 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/DWRC-UCA.sofa differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/Download_Example_sofa_file.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/Download_Example_sofa_file.m new file mode 100644 index 0000000000000000000000000000000000000000..9ea66634067a57a3b1adde6940f3f70ae36920bd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/Download_Example_sofa_file.m @@ -0,0 +1,21 @@ +%% put your information here: +hrtf = SOFAload('path/to_your/HRTF.sofa'); +soundInput = audioread('path/to_your/fancy_audio_file.wav'); + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(hrtf.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/OfficeII.sofa b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/OfficeII.sofa new file mode 100644 index 0000000000000000000000000000000000000000..9c64c63055966c6aba82974a40c98b9a94cb6d62 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA-files/OfficeII.sofa differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAaddVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAaddVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..c87b65bdeb1d6743b0acb34f0b295fde621b1d28 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAaddVariable.m @@ -0,0 +1,59 @@ +function Obj = SOFAaddVariable(Obj,Name,Dim,Value) +%SOFAaddVariable +% Obj = SOFAaddVariable(Obj,Name,Dim,Value) adds a user-defined variable +% to the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). DIM is a string +% describing the dimensions of the variable according to SOFA specifications. +% The content of NAME is stored in VALUE which must be of the size DIM. +% The used-defined variable NAME will be stored as Obj.NAME and its +% dimension will be stored as Obj.API.Dimensions.NAME. Note that user- +% defined variables can be saved in SOFA file and thus remain in the +% object when loaded from a SOFA file. +% +% Obj = SOFAaddVariable(Obj,Name,'PRIVATE',Value) adds a private variable +% to OBJ. The private variable NAME will be stored as Obj.PRIVATE.NAME. +% Note that the private variables will be not stored in SOFA files and +% arbitrary dimensions are allowed. +% +% Note that adding variables to Data is not supported and should not be used +% as it might be confusing having user-defined variables in a Data structure. +% Consider adding a variable at the global level instead, which would be more +% clear for others. + +% 9.8.2014: dimension is added if not previously found. +% +% SOFA API - function SOFAaddVariable +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Dim=upper(Dim); +switch Dim + case 'PRIVATE' + Obj.PRIVATE.(Name)=Value; + otherwise + switch Name + case {'API','PRIVATE','GLOBAL'} + error('This variable name is reserved.'); + otherwise + if strncmp(Name,'Data.',length('Data.')) + % add variable to Data + Name=Name(length('Data.')+1:end); + Obj.Data.(Name)=Value; + Obj.API.Dimensions.Data.(Name)=Dim; + else + % add variable to root + Obj.(Name)=Value; + Obj.API.Dimensions.(Name)=Dim; + end + dims=SOFAdefinitions('dimensions'); + for ii=1:length(Dim) + if ~isfield(dims,Dim(ii)) + error('Dimension not supported.'); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAappendText.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAappendText.m new file mode 100644 index 0000000000000000000000000000000000000000..7553f41597fdb387faec6145b3193d803074c9d2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAappendText.m @@ -0,0 +1,24 @@ +function output = SOFAappendText(Obj,attribute,new) +%SOFAappendText +% +% output = SOFAappendText(Obj,attribute,new) appends the new text to the +% attribute (as string) using the correct SOFA separators. If the attribute is empty +% or non-existing, the output will be the new text only. +% +% example: +% Obj.GLOBAL_Title = SOFAappendText(Obj, 'GLOBAL_Title', 'Append me to the title.'); + +% SOFA API - function SOFAappendText +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~isfield(Obj,attribute), Obj.(attribute)=''; end +if isempty(Obj.(attribute)), + output=new; +else + output=[Obj.(attribute) SOFAdefinitions('EOL') new]; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAarghelper.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAarghelper.m new file mode 100644 index 0000000000000000000000000000000000000000..78df203847da206cad59dca8aa599741b1f7a94d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAarghelper.m @@ -0,0 +1,273 @@ +function [flags,keyvals,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun) +%SOFAARGHELPER Parse arguments for SOFA +% Usage: [flags,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun); +% +% Input parameters: +% posdepnames : Names of the position dependant parameters. +% definput : Struct to define the allowed input +% arglist : Commandline of the calling function (varargin) +% callfun : Name of calling function (optional) +% +% Output parameters: +% flags : Struct with information about flags. +% keyvals : Struct with key / values. +% varargout : The position dependant pars. properly initialized +% +% [flags,keyvals]=SOFAARGHELPER(posdepnames,definput,arglist) assists in +% parsing input parameters for a function. Parameters come in +% four categories: +% +% Position dependant parameters. These must not be strings. These are +% the first parameters passed to a function, and they are really just a short way +% of specifying key/value pairs. See below. +% +% Flags. These are single string appearing after the position dependant +% parameters. +% +% Key/value pairs. The key is always a string followed by the value, which can be +% anything. +% +% Expansions. These appear as flags, that expand into a pre-defined list of parameters. +% This is a short-hand way of specifying standard sets of flags and key/value pairs. +% +% The parameters are parsed in order, so parameters appearing later in varargin will override +% previously set values. +% +% The following example for calling SOFAARGHELPER is taken from DGT: +% +% definput.keyvals.L=[]; +% definput.flags.phase={'freqinv','timeinv'}; +% [flags,kv]=SOFAarghelper({'L'},definput,varargin); +% +% The first line defines a key/value pair with the key 'L' having an initial value of `[]` +% (the empty matrix). +% +% The second line defines a group of flags by the name of phase. The +% group phase contains the flags `'freqinv'` and `'timeinv'`, which can +% both be specified on the command line by the user. The group-name +% phase is just for internal use, and does not appear to the user. The +% flag mentioned first in the list will be selected by default, and only +% one flag in a group can be selected at any time. A group can contain as +% many flags as desired. +% +% The third line is the actual call to SOFAARGHELPER which defines the +% output flags and `kv`. The input `{'L'}` indicates that the value of +% the parameter 'L' can also be given as the very first value in +% varargin. +% +% The output struct kv contains the key/value pairs, so the value associated to `'L'` is +% stored in kv.L. +% +% The output struct flags contains information about the flags choosen +% by the user. The value of flags.phase will be set to the selected flag +% in the group phase and additionally, the value of `flags.do_timeinv` +% will be 1 if 'timeinv' was selected and 0 otherwise, and similarly for +% 'freqinv'. This allows for easy checking of selected flags. +% + +% Copyright (C) 2005-2012 Peter L. Soendergaard. +% Modified from the LTFAT 1.1.2 for SOFA by Piotr Majdak. +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. + +persistent SOFA_CONF; + +if isempty(SOFA_CONF) + SOFA_CONF.fundefs = struct; +end; + +if ischar(posdepnames) + % Special interface needed for ltfatsetdefaults and ltfatgetdefaults, + % activated when first argument is a string. + + % First input argument, posdepnames, is a string, one of the options + % in the "switch" section below + % Second input argument, definput, is a function name to get or set + % Third input argument, arglist , is a cell-array with options to set. + + switch(lower(posdepnames)) + case 'get' + if isfield(SOFA_CONF.fundefs,definput) + flags=SOFA_CONF.fundefs.(definput); + else + flags={}; + end; + case 'set' + SOFA_CONF.fundefs.(definput)=arglist; + case 'all' + flags=SOFA_CONF.fundefs; + case 'clearall' + SOFA_CONF.fundefs=struct; + end; + return +end; + +if nargin<4 + f=dbstack; + callfun=f(2).name; +end; + +nposdep=numel(posdepnames); + +% Resolve import specifications BEFORE adding our own specifications. +if isfield(definput,'import') + for imp = definput.import; + definput=feval(['arg_',imp{1}],definput); + end; +end; + +if isfield(definput,'flags') + defflags=definput.flags; +else + defflags=struct; +end; + +if isfield(definput,'keyvals') + defkeyvals=definput.keyvals; +else + defkeyvals=struct; +end; + +if isfield(definput,'groups') + groups=definput.groups; +else + groups=struct; +end; + +total_args = numel(arglist); + +% Determine the position of the first optional argument. +% If no optional argument is given, return nposdep+1 +first_str_pos = 1; +while first_str_pos<=total_args && ~ischar(arglist{first_str_pos}) + first_str_pos = first_str_pos +1; +end; + +% If more than nposdep arguments are given, the first additional one must +% be a string +if (first_str_pos>nposdep+1) + error('%s: Too many input arguments',upper(callfun)); +end; + +n_first_args=min(nposdep,first_str_pos-1); + +keyvals=defkeyvals; + +% Copy the given first arguments +for ii=1:n_first_args + keyvals.(posdepnames{ii})=arglist{ii}; +end; + +% Initialize the position independent parameters. +% and create reverse mapping of flag -> group +flagnames=fieldnames(defflags); +flags=struct; +% In order for flags to start with a number, it is necessary to add +% 'x_' before the flag when the flags are used a field names in +% flagreverse. Externally, flags are never used a field names in +% structs, so this is an internal problem in ltfatarghelper that is +% fixed this way. +flagsreverse=struct; +for ii=1:numel(flagnames) + name=flagnames{ii}; + flaggroup=defflags.(name); + flags.(name)=flaggroup{1}; + for jj=1:numel(flaggroup) + flagsreverse.(['x_', flaggroup{jj}])=name; + flags.(['do_',flaggroup{jj}])=0; + end; + flags.(['do_',flaggroup{1}])=1; +end; + +%Get the rest of the arguments +restlist = arglist(first_str_pos:end); + +%Check for default arguments +if isfield(SOFA_CONF.fundefs,callfun) + s=SOFA_CONF.fundefs.(callfun); + restlist=[s,restlist]; +end; + +% Check for import defaults +if isfield(definput,'importdefaults') + % Add the importdefaults before the user specified arguments. + restlist=[definput.importdefaults,restlist]; +end; + +while ~isempty(restlist) + argname=restlist{1}; + restlist=restlist(2:end); % pop + found=0; + + % Is this name a flag? If so, set it + if isfield(flagsreverse,['x_',argname]) + % Unset all other flags in this group + flaggroup=defflags.(flagsreverse.(['x_',argname])); + for jj=1:numel(flaggroup) + flags.(['do_',flaggroup{jj}])=0; + end; + + flags.(flagsreverse.(['x_',argname]))=argname; + flags.(['do_',argname])=1; + found=1; + end; + + % Is this name the key of a key/value pair? If so, set the value. + if isfield(defkeyvals,argname) + keyvals.(argname)=restlist{1}; + restlist=restlist(2:end); + found=1; + end; + + % Is this name a group definition? If so, put the group in front of the parameters + if isfield(groups,argname) + s=groups.(argname); + restlist=[s,restlist]; + found=1; + end; + + % Is the name == 'argimport' + if strcmp('argimport',argname) + fieldnames_flags= fieldnames(restlist{1}); + fieldnames_kvs = fieldnames(restlist{2}); + for ii=1:numel(fieldnames_flags) + importname=fieldnames_flags{ii}; + flags.(importname)=restlist{1}.(importname); + end; + for ii=1:numel(fieldnames_kvs) + importname=fieldnames_kvs{ii}; + keyvals.(importname)=restlist{2}.(importname); + end; + restlist=restlist(3:end); + found=1; + end; + + if found==0 + if ischar(argname) + error('%s: Unknown parameter: %s',upper(callfun),argname); + else + error('%s: Parameter is not a string, it is of class %s',upper(callfun),class(argname)); + end; + end; + + %ii=ii+1; +end; + +% Fill varargout + +varargout=cell(1,nposdep); +for ii=1:nposdep + varargout(ii)={keyvals.(posdepnames{ii})}; +end; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcalculateAPV.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcalculateAPV.m new file mode 100644 index 0000000000000000000000000000000000000000..aa36aa4c7970ff1a374cd60c9f09397f54cfdd5c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcalculateAPV.m @@ -0,0 +1,73 @@ +function ApparentPositionVector = SOFAcalculateAPV(Obj) +%SOFAcalculateAPV +% APV = SOFAcalculateAPV(Obj) calculates the apparent position vector +% (APV) which represents the position of the source relative to the +% listener's position and view. APV is in the format [azi ele radius] +% with units [deg deg m]. +% Note that ListenerUp is not considered and the APV can be considered as +% the HRTF direction usually used in HRTF databases + +% SOFA API - function SOFAcalculateAPV +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% === Apparent azimuth === +% Apparent azimuth is the relative direction of the sound source in the +% horizontal plane from the listener viewpoint +% +% Get head orientation of the listener and source position in spherical +% coordinates +HeadOrientation = SOFAconvertCoordinates( ... + Obj.ListenerView,Obj.ListenerView_Type,'spherical'); +SourcePosition = SOFAconvertCoordinates( ... + Obj.SourcePosition,Obj.SourcePosition_Type,'spherical'); +% Calculate the relative azimuth angle between them +APVazimuth = correctAzimuth(bsxfun( ... + @minus,SourcePosition(:,1),HeadOrientation(:,1))); + +% === Apparent elevation === +% Apparent elevation is the relative direction of the sound source in the median +% plane from the listener viewpoint +APVelevation = correctElevation(bsxfun( ... + @minus,SourcePosition(:,2),HeadOrientation(:,2))); + +% === Apparent distance === +% Apparent distance is the relative distance between the sound source and the +% listener +% +% Get listener positon in spherical coordinates +ListenerPosition = SOFAconvertCoordinates( ... + Obj.ListenerPosition,Obj.ListenerPosition_Type,'spherical'); +% Relative distance +APVdistance = bsxfun(@minus,SourcePosition(:,3),ListenerPosition(:,3)); + +% Combine to matrix +ApparentPositionVector = [ ... + APVazimuth, ... + APVelevation, ... + APVdistance, ... +]; + +end + +function phi = correctAzimuth(phi) + % Ensure -360 <= phi <= 360 + phi = rem(phi,360); + % Ensure -180 <= phi < 180 + phi(phi<-180) = phi(phi<-180) + 360; + phi(phi>=180) = phi(phi>=180) - 360; +end + +% TODO: check what convetion we are using for delta! +function delta = correctElevation(delta) + % Ensure -180 <= delta <= 180 + delta = correctAzimuth(delta); + % Ensure -90 <= delta <= 90 + delta(delta<-90) = -delta(delta<-90) - 180; + delta(delta>90) = -delta(delta>90) + 180; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcheckFilename.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcheckFilename.m new file mode 100644 index 0000000000000000000000000000000000000000..13434e4cf69365bae028e29bdcda6277119856cc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcheckFilename.m @@ -0,0 +1,26 @@ +function newfn=SOFAcheckFilename(fn) +%SOFACHECKFILENAME +% newFN = SOFAcheckFilename(FN) checks the filename FN and: + +% SOFA API - function SOFAcheckFilename +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% filename = string? +if ~ischar(fn) + error('Filename must be a string.'); +end +if strcmp(fn(1:7),'http://') + newfn=fn; % remote file +else + fn=strrep(fn,'/',filesep); + fn=strrep(fn,'\',filesep); + if length(fn)>4 + if strcmpi(fn(1:4),['db:' filesep]), fn=[SOFAdbPath fn(5:end)]; end + end + newfn=fn; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..a8f61211061cfe6929cc3a5034e9928df0494cc8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompact.m @@ -0,0 +1,89 @@ +function [Obj, log] = SOFAcompact(Obj) +%SOFAcompact +% Obj = SOFAcompact(Obj) compacts the unique value to singleton dimensions +% of variables where possible. +% Current limitation: Variables with 3 dimensions will be only compacted +% when the third dimension is the compressible one. +% + +% SOFA API - function SOFAcompact +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence") +% You may not use this work except in compliance with the Licence. +% You may obtain a copy of the Licence at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the Licence for the specific language governing permissions and limitations under the Licence. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); +dims=SOFAdefinitions('dimensions'); + +%% compact w/o data +X=rmfield(Obj,{'Data','API'}); +Xf=fieldnames(X); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % get all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.(Xf{ii}),'rows'); else n=unique(Obj.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.(Xf{ii})=n; else Obj.(Xf{ii})=n'; end; % compressed! + case 3 + d=cell2mat(strfind(dims,'I')); + switch d + case 3 + y=unique(reshape(Obj.(Xf{ii}),[],size(Obj.(Xf{ii}),d))','rows'); + if size(y,1)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=reshape(y',size(Obj.(Xf{ii}),1),size(Obj.(Xf{ii}),2)); + otherwise + warning('SOFA:compact',[Xf{ii} ' not compressed (currently limited)']); + end + end +end + +%% Compact the data +Xf=fieldnames(Obj.Data); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.Data.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.Data.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.Data.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.Data.(Xf{ii}),'rows'); else n=unique(Obj.Data.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.Data.(Xf{ii})=n; else Obj.Data.(Xf{ii})=n'; end; % compressed! + case 3 + % missing + warning('SOFA:compact',['Data.' Xf{ii} ' not compressed (functionality limited)']); + end +end + +%% clean up +Obj=SOFAupdateDimensions(Obj); +if length(log)>1, log=log(2:end); else log={}; end; + +function vec=getdim(Obj,str) +vec=NaN(1,length(str)); +for ii=1:length(str) + vec(ii)=Obj.(upper(str(ii))); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompare.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompare.m new file mode 100644 index 0000000000000000000000000000000000000000..c0a5db8e763bcaf38a02fce4ebaf9db59cef87c6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompare.m @@ -0,0 +1,57 @@ +function [tf,reason,where] = SOFAcompare(Obj1, Obj2, varargin) +%SOFASOFAcompare +% TF = SOFAcompare(A, B) compares A and B and +% returns logical 1 (true) if they are identical. +% +% [TF,REASON,WHERE] = SOFAcompare(A, B) provides the REASON +% and shows WHERE the difference arose. +% +% ... = SOFAcompare(A, B, 'ignoreDate') ignores the global attributes +% DateCreated and DateModified. +% +% +% Limited functionality!!! Only attributes are compared now. +% +% +% + +% SOFA API - function SOFAcompare +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.flags.type={'all','ignoreDate'}; +[flags,~]=SOFAarghelper({},definput,varargin); + + +tf=1; +reason=''; +where=''; + +% % check if the size is equal +% o1=whos('Obj1'); +% o2=whos('Obj2'); +% if o1.bytes ~= o2.bytes, tf=0; reason='Different size'; return; end + + % get the field names +Xf=fieldnames(Obj1); + + % ignore DateCreated and DateModified? +if flags.do_ignoreDate + Xf=fieldnames(rmfield(Obj1,{'GLOBAL_DateCreated','GLOBAL_DateModified'})); +end + + % check if we have the same fields in Obj2 as in Obj1 +for ii=1:length(Xf) + if ~isfield(Obj2,Xf{ii}), tf=0; reason='Field missing in B'; where=Xf{ii}; return; end +end + + % check if we have the same content of attributes in Obj2 as in Obj1 +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), continue; end + if ~strcmp(Obj1.(Xf{ii}),Obj2.(Xf{ii})), tf=0; reason='Field not equal'; where=Xf{ii}; return; end +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompileConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompileConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..45cfe151cdbaea301623e517f33c262bceebbe5c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAcompileConventions.m @@ -0,0 +1,190 @@ +function SOFAcompileConventions(conventions) +%SOFAcompileConventions +% +% Obj = SOFAcompileConventions(sofaconventions) compiles the specified +% SOFA conventions. For every convention a CSV file has to exist which +% will be compiled to a .mat file used later by SOFAgetConventions(). +% +% The CSV file must be in the directory conventions and have the same +% filename as conventions. SOFAcompileConventions generates 3 files, one +% for each flag (r, m, and all). +% +% Before compiling, SOFAcompileConventions checks if the modification +% date of the .mat files is older than that of the .csv file. Compiling +% is not performed if all .mat files are newer than the .csv file. This +% behaviour is required for operation in a read-only directory. + +% SOFA API +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +baseFolder = fileparts(which('SOFAstart')); + +if nargin<1 + conventionFiles = dir(fullfile(baseFolder,'conventions','*.csv')); + conventions={}; + for file = conventionFiles' + [~,name,ext] = fileparts(file.name); + % Check if mat files exist for every convention flag (r,m,a) + flagsCounter = 0; + for flag = 'rma' + flagFile = dir(fullfile(baseFolder,'conventions', ... + strcat(name,'-',flag,'.mat'))); + if ~isempty(flagFile) && flagFile(1).datenum>file.datenum + flagsCounter = flagsCounter+1; + end + end + % If not all three files are up to request conventions compilation + if flagsCounter~=3 + conventions{end+1} = name; + end + end +elseif ~iscell(conventions) + conventions={conventions}; +end + + +%% ----- Convert convention csv files into mat files ----- +for convention = conventions + % Read convention description from csv file + fid = fopen(fullfile(baseFolder,'conventions', ... + strcat(convention{:},'.csv'))); + if exist('OCTAVE_VERSION','builtin') + % We're in Octave where textscan works differently since ver. 4.2 + C_lines = textscan(fid,'%s','Delimiter','\n','Headerlines',1); + C_line = C_lines{1}{1}; + C_elems = cell(length(C_lines{1}),1); + for line_nr = 1:length(C_lines{1}) + C_line = C_lines{1}{line_nr}; + C_elems{line_nr} = strsplit(C_line, '\t', 'collapsedelimiters', false); + end + C = cell(1,length(C_elems{1})); + for col_nr = 1:length(C_elems{1}) + C{col_nr} = cell(length(C_lines{1}),1); + end + for line_nr = 1:length(C_lines{1}) + for col_nr = 1:length(C_elems{1}) + C{col_nr}{line_nr} = C_elems{line_nr}{col_nr}; + end + end + else + x=char(fread(fid)); + xr=strrep(x',char([9 13 10]),char([9 32 32 13 10])); + C = textscan(xr,'%s%s%s%s%s%s','Delimiter','\t','Headerlines',1,'WhiteSpace',''); + end + fclose(fid); + + % Convert to mat files for r,m,a cases + for flag = 'rma' + % Convert to SOFA object + Obj = compileConvention(C,flag); + % Write to mat file + if strcmp(Obj.GLOBAL_SOFAConventions,convention{:}) + if strcmp(flag,'r') % Display message only the very first time + disp(['Compiling ',convention{:},' ', ... + Obj.GLOBAL_SOFAConventionsVersion]); + end + save(fullfile(baseFolder,'conventions', ... + strcat(convention{:},'-',flag,'.mat')), ... + 'Obj','-v7'); + else + warning([convention{:} '.csv: file name not convention name (' Obj.GLOBAL_SOFAConventions]); + end + end +end +end % of main function + + +%% ----- Subroutines ----------------------------------------------------- +function Obj = compileConvention(convention,flag) + % Compile convention mat structure for the specified flag + % + % The csv files provide the following columns (corresponding cell numbers in + % brackets) + % Name {1}, Default {2}, Flags {3}, Dimensions {4}, Type {5}, Comment {6} + convName = convention{1}; + convDefault = convention{2}; + convFlags = convention{3}; + convDimensions = convention{4}; + convType = convention{5}; + convComment = convention{6}; + + % Create object structure + for ii=1:length(convName) + % Append 'a' to Flags entry as it only contains 'm' or 'r' in the csv file + convFlags{ii} = strcat(convFlags{ii},'a'); + if ~isempty(regexp(convFlags{ii},flag)) + var = regexprep(convName{ii},':','_'); + switch lower(convType{ii}) + case 'double' + % Convert default to double + convDefault{ii} = str2num(convDefault{ii}); + case 'string' + eval(['convDefault{ii}=' convDefault{ii} ';']); + end + if isempty(strfind(var,'Data.')) + Obj.(var) = convDefault{ii}; + if isempty(strfind(var,'_')) % && ~sum(strcmp(var,dims)) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quotations and insert line breaks + Obj.API.Dimensions.(var)=eval(['{''' y '''}']); + end + else + Obj.Data.(var(6:end)) = convDefault{ii}; + if isempty(strfind(var(6:end),'_')) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quatations and insert line breaks + Obj.API.Dimensions.Data.(var(6:end))=eval(['{''' y '''}']); + end + end + end + end + + + % ----- Overwrite some special fields ----- + if isfield(Obj,'GLOBAL_APIVersion') + Obj.GLOBAL_APIVersion = SOFAgetVersion; + end + if isfield(Obj,'GLOBAL_APIName') + Obj.GLOBAL_APIName = 'ARI Matlab/Octave API'; + end + + % ----- Create dimension size variables - if not read-only ----- + if strcmp(flag,'r') + return; + else + % Fix dimension sizes (why we have to fix them?) + Obj.API.I = 1; + Obj.API.C = 3; + % Variable-dependent dimension sizes + dims = 'renm'; + % Check all metadata variables + fields =fieldnames(rmfield(Obj.API.Dimensions,'Data')); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(fields{jj}),dim(1)); + break; + end + end + end + % Check all data variables + fields = fieldnames(Obj.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.Data.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fields{jj}),dim(1)); + break; + end + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAconvertConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAconvertConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..986e2167b951d3c925d4eade50a2051a619a9af5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAconvertConventions.m @@ -0,0 +1,78 @@ +function Obj=SOFAconvertConventions(Obj) +% SOFAconvertConventions(OBJ) converts an object to SimpleFreeFieldHRIR +% +% Supported conventions: +% SimpleFreeFieldSOS +% SimpleFreeFieldTF +% some special cases of GeneralTF. + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Convert data to SimpleFreeFieldHRIR +switch Obj.GLOBAL_SOFAConventions + case 'SimpleFreeFieldSOS' + N=512; + impulse=[1; zeros(N-1,1)]; + T=SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_SOFAConventions=T.GLOBAL_SOFAConventions; + Obj.GLOBAL_SOFAConventionsVersion=T.GLOBAL_SOFAConventionsVersion; + Obj.GLOBAL_DataType=T.GLOBAL_DataType; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + Obj.Data.IR(ii,jj,:)=sosfilt(reshape(squeeze(Obj.Data.SOS(ii,jj,:)),6,[])',impulse); + end + end + Obj.Data=rmfield(Obj.Data,'SOS'); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,'N'); + Obj=SOFAupdateDimensions(Obj); + case {'SimpleFreeFieldTF' 'GeneralTF'} + fs=48000; %max(Obj.N)*2; + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + T=SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_SOFAConventions=T.GLOBAL_SOFAConventions; + Obj.GLOBAL_SOFAConventionsVersion=T.GLOBAL_SOFAConventionsVersion; + Obj.GLOBAL_DataType=T.GLOBAL_DataType; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=fs; + Obj.Data.SamplingRate_Units='Hertz'; + Obj.Data.IR_LongName=Obj.Data.Real_LongName; + Obj.Data.IR_Units=Obj.Data.Real_Units; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(N/2+1,1); + s(Obj.N*N/fs+1)=squeeze(Obj.Data.Real(ii,jj,:))+1i*squeeze(Obj.Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,T.SourcePosition_Type,Obj.SourcePosition_Units,T.SourcePosition_Units); + end + Obj.Data.Delay=zeros(1,Obj.API.R); + Obj.SourcePosition_Type=T.SourcePosition_Type; + Obj.SourcePosition_Units=T.SourcePosition_Units; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag','Real_LongName','Imag_LongName','Real_Units','Imag_Units'}); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,'N'); + Obj=SOFAupdateDimensions(Obj); + otherwise + error('Conventions not supported'); +end + + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end; +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAconvertCoordinates.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAconvertCoordinates.m new file mode 100644 index 0000000000000000000000000000000000000000..550d9cb8d4358ffdb306cd1eda3389e01b12b284 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAconvertCoordinates.m @@ -0,0 +1,60 @@ +function output = SOFAconvertCoordinates(input,input_type,output_type,input_unit,output_unit) +%SOFAconvertCoordinates +% output = SOFAconvertCoordinates(input,input_type,output_type,input_unit, +% output_unit), converts the specified coordinate variable to specified +% output_type and returns the results. + +% SOFA API - function SOFAconvertCoordinates +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% check input +if strcmp(input_type,'cartesian')==0 && ... + strcmp(input_type,'spherical')==0 && ... + strcmp(input_type,'geodesic')==0 && ... + strcmp(input_type,'horizontal-polar')==0 + error('Specified "input_type" is not supported'); +end +if strcmp(output_type,'cartesian')==0 && ... + strcmp(output_type,'spherical')==0 && ... + strcmp(output_type,'geodesic')==0 && ... + strcmp(output_type,'horizontal-polar')==0 + error('Specified "output_type" is not supported'); +end + +output=input; +%% convert coordinates if necessary +if strcmp(output_type,input_type)==0 + temp=input; + switch input_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [temp(:,1),temp(:,2),temp(:,3)]=sph2cart(deg2rad(input(:,1)),deg2rad(input(:,2)),input(:,3)); + case 'horizontal-polar' + [temp(:,1),temp(:,3),temp(:,2)]=sph2cart(deg2rad(input(:,2)),deg2rad(input(:,1)),input(:,3)); + temp(:,2)=-temp(:,2); + end + + output=temp; + switch output_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [output(:,1),output(:,2),output(:,3)]=cart2sph(temp(:,1),temp(:,2),temp(:,3)); + output(:,1:2)=rad2deg(output(:,1:2)); + case 'horizontal-polar' + [output(:,2),output(:,1),output(:,3)]=cart2sph(temp(:,1),temp(:,3),-temp(:,2)); + output(:,1:2)=rad2deg(output(:,1:2)); + output(:,1)=-output(:,1); + output(:,2)=mod(output(:,2),360); + end +end + + + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdbPath.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdbPath.m new file mode 100644 index 0000000000000000000000000000000000000000..02ed92a057d48753b9965b68abb9c35671c9c2d7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdbPath.m @@ -0,0 +1,32 @@ +function dbPath=SOFAdbPath(newPath) +% dbPath=SOFAdbPath +% +% dbPath=SOFAdbPath returns the path to the directory containing +% HRTFs for demos and applications. The default path is: this_directory/../HRTFs/SOFA +% +% [...]=SOFAdbPath(Path) sets the path to the directory for further calls +% of SOFAdbPath. + +% SOFA API - function SOFAstart +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedPath; + +if exist('newPath','var') + if strcmp(newPath,'reset') + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'HRTFs','SOFA'); + else + CachedPath=newPath; + end +elseif isempty(CachedPath) + % default: 'this_directory/../HRTFs/SOFA' + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'HRTFs','SOFA'); +end +dbPath=CachedPath; + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdbURL.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdbURL.m new file mode 100644 index 0000000000000000000000000000000000000000..4083a3c31a0b92928f658101830262fa7fc1564e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdbURL.m @@ -0,0 +1,29 @@ +function dbURL=SOFAdbURL(dbURL) +% dbURL=SOFAdbURL +% +% dbURL=SOFAdbURL returns the internet URL to the directory containing +% HRTFs. The default URL is http://www.sofacoustics.org/data. +% +% dbURL=SOFAdbURL(newURL) sets the internet URL to the newURL for further calls +% of SOFAdbURL. + +% SOFA API - function SOFAdbURL +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedURL; + +if exist('dbURL','var') + if strcmp(dbURL,'reset') + CachedURL='http://www.sofacoustics.org/data'; + else + CachedURL=dbURL; + end +elseif isempty(CachedURL) + CachedURL='http://www.sofacoustics.org/data'; +end +dbURL=CachedURL; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdefinitions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdefinitions.m new file mode 100644 index 0000000000000000000000000000000000000000..abc1e84dbb9d955d52e804efb8c8c8dda4ff664f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAdefinitions.m @@ -0,0 +1,80 @@ +function output = SOFAdefinitions(varargin) +% SOFAdefinitions +% +% SOFAdefinitions returns a struct containing definitions like the time +% format used in the API. +% +% SOFAdefinitions('dateFormat') returns the date format +% +% SOFAdefinitions('APIName') returns the APIName +% +% SOFAdefinitions('dimensions') returns the dimensions used in the API +% +% SOFAdefinitions('EOL') returns the end-of-line separator used in the API +% +% SOFAdefinitions('dateReference') returns the string with the reference +% for the date when stored as numeric (number of seconds elapsed) +% +% SOFAdefinitions('units') returns the units and their corresponding aliases +% + +% SOFA API - function SOFAdefinitions +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +definput.flags.type={'all','dateFormat','APIName','dimensions','EOL','dateReference','units'}; +[flags,kv]=SOFAarghelper({},definput,varargin); + +%% Return all definitions in a structure +if flags.do_all, + output.APIName = SOFAdefinitions('APIName'); + output.dateFormat = SOFAdefinitions('dateFormat'); + output.dimensions = SOFAdefinitions('dimensions'); + output.EOL = SOFAdefinitions('EOL'); + output.dateReference = SOFAdefinitions('dateReference'); + output.units=SOFAdefinitions('units'); +end + +%% name of the API +if flags.do_APIName, + output = 'ARI SOFA API for Matlab/Octave'; +end + +%% date string to use (see help datestr) +if flags.do_dateFormat, + output = 'yyyy-mm-dd HH:MM:SS'; +end + +%% EOL to use +if flags.do_EOL, + output = char(10); +end + +%% dimensions to use +if flags.do_dimensions, + output.M = 'M'; % Number of Measurements + output.R = 'R'; % Number of Receivers + output.N = 'N'; % Number of Samples or the way you represent your data + output.E = 'E'; % Number of Emitters + output.C = 'C'; % Coordinates + output.I = 'I'; % Singleton + output.S = 'S'; % size of the largest string +end + +%% reference for date when used as numeric (number of seconds elapsed) +if flags.do_dateReference, + output = '1970-01-01 00:00:00'; +end + +%% return units with defined aliases +if flags.do_units, + output.metre={'metres','meter','meters'}; + output.degree={'degrees'}; + output.second={'seconds'}; +end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAexpand.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAexpand.m new file mode 100644 index 0000000000000000000000000000000000000000..40de3a82603db63dc6d70c54a2b14e04c7b8ebe2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAexpand.m @@ -0,0 +1,136 @@ +function [Obj, log] = SOFAexpand(Obj,VarName) +%SOFAexpand +% Obj = SOFAexpand(Obj) expands the singleton dimensions of all variables. +% Only variables will be expanded. Data and attributes won't. Note that +% also Obj.API.Dimensions will be updated to the new dimensions. +% +% Obj = SOFAexpand(Obj,VarName) expands the singleton dimensions of +% the variable VarName. +% +% [Obj,log] = SOFAexpand(...) returns a log of expanded variables. + +% SOFA API - function SOFAexpand +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj,'nodata'); + +%% If VarName given, expand a single variable only +if ~exist('VarName','var'), + + %% Expand all variables + % create field names which should have dimensions + X=rmfield(Obj,{'Data','API'}); + if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end + Xf=fieldnames(X); + + % Update the dimensions structure w/o data + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.(Xf{ii})=varNew; + Obj.API.Dimensions.(Xf{ii})=dimNew; + log{end+1}=[Xf{ii} ' expanded to ' dimNew]; + end + end + + % Expand the dimensions of Data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.Data.(Xf{ii})=varNew; + Obj.API.Dimensions.Data.(Xf{ii})=dimNew; + log{end+1}=['Data.' Xf{ii} ' expanded to ' dimNew]; + end + end + + +else % Expand a single variable only + if isempty(strfind(VarName,'_')), % is an attribute --> not expandable + if strncmp(VarName,'Data.',length('Data.')) + % variable within the Data. structure + VarName=VarName(length('Data.')+1:end); + if isfield(OC.API.Dimensions.Data, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,VarName,dim); + if ~isempty(varNew), + Obj.Data.(VarName)=varNew; + Obj.API.Dimensions.Data.(VarName)=dimNew; + log{end+1}=['Data.' VarName ' expanded to ' dimNew]; + end + end + end + else + if isfield(OC.API.Dimensions, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,VarName,dim); + if ~isempty(varNew), + Obj.(VarName)=varNew; + Obj.API.Dimensions.(VarName)=dimNew; + log{end+1}=[VarName ' expanded to ' dimNew]; + end + end + end + end + end +end + +%% log variable +if length(log)>1, log=log(2:end); else log={}; end; + +%% expand a single variable +% Obj: the full SOFA object +% f: name of the variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expand(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.(f),ones(getdim(Obj,dN))); + end + if ~exist('var','var'), var=[]; dN=[]; end; +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); + +%% expand a single Data variable +% Obj: the full SOFA object +% f: name of the Data variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expandData(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.Data.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.Data.(f),ones(getdim(Obj,dN))); + end + if ~exist('var','var'), var=[]; dN=[]; end; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAfind.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAfind.m new file mode 100644 index 0000000000000000000000000000000000000000..4d6712362fc6f9fab57f0c2b2bf1264dba8ca4c4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAfind.m @@ -0,0 +1,47 @@ +function [idx, azinew, elenew, rnew] = SOFAfind(Obj,azi,ele,r) +% SOFAfind +% [idx, azi, ele, r] = SOFAfind(Obj,azi,ele,r) finds the indecies to +% the HRTFs from OBJ according to the trajectory given in AZI, ELE, R. +% Input: +% Obj: SOFA object containing HRTFs +% azi, ele: direction (in degrees) for azimuth and elevation +% r: optional radius. If not provided, radius will be ignored. +% +% Output: +% idx: index of the filters (corresponds to AZI and ELE) +% azi, ele: azimuth and elevation of the actual position (degrees) +% r: actual radius +% +% +% +% Piotr Majdak, 2019 + +% SOFA API - SOFAfind +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + +%% create a 2D-grid with nearest positions +if ~exist('r','var'), + r=1; + Obj.SourcePosition(:,3)=r; +end +pos=SOFAconvertCoordinates(Obj.SourcePosition,'spherical','cartesian'); +idx=zeros(length(azi),1); +for ii=1:length(azi) + [t(:,1),t(:,2),t(:,3)] = sph2cart(deg2rad(azi(ii)),deg2rad(ele(ii)),r); + dist = sum((pos-repmat(t,size(pos,1),1)).^2,2); + [~,idx(ii)]=min(dist); +end + +%% Output +% actually used angles +azinew = Obj.SourcePosition(idx,1); +elenew = Obj.SourcePosition(idx,2); +rnew = Obj.SourcePosition(idx,3); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAgetConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAgetConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..de1aa44e57c177397ff489fc67ad958664a04868 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAgetConventions.m @@ -0,0 +1,68 @@ +function Obj = SOFAgetConventions(sofaconventions,flags) +%SOFAgetConventions +% +% List = SOFAgetConventions() returns a list with supported conventions. +% +% Obj = SOFAgetConventions(sofaconvention) returns a SOFA object +% with all metadata and data for the corresponding sofaconvention. Obj +% will be empty if sofaconventions is not supported. +% +% Obj = SOFAgetConventions(sofaconvention,flags) returns only selected +% metadata for the corresponding sofaconvention with the following encoding: +% m: mandatory +% r: readonly +% a: all (default) + +% SOFA API - function SOFAgetConventions +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% If sofaconventions not provided, return the list with supported conventions +if ~exist('sofaconventions','var') + p=mfilename('fullpath'); + d=dir([p(1:length(p)-length(mfilename)) 'conventions' filesep '*-m.mat']); + Obj={}; + for ii=1:length(d) + dn=d(ii).name; + Obj{ii}=dn(1:end-6); + end + return; +end + +%% If flags not provided, return the conventions with all metadata +if ~exist('flags','var') + flags='a'; % flags: m: mandatory, r: readonly, a: all +end + +%% Load cached object +persistent AllObj; + +found=0; +if isfield(AllObj,flags) + if isfield(AllObj.(flags).Obj,'GLOBAL_SOFAConventions') + if strcmp(AllObj.(flags).Obj.GLOBAL_SOFAConventions,sofaconventions) + found=1; + end + end +end +if found, + Obj=AllObj.(flags).Obj; % return cached convention object +else + p=mfilename('fullpath'); + if ~isempty(dir([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '-' flags '.mat'])) + AllObj.(flags)=load([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '-' flags '.mat']); + Obj=AllObj.(flags).Obj; % load conventions to the cache and return + else + Obj=[]; % return empty array when conventions not found + end +end + + +%% Overwrite some special fields +if isfield(Obj,'GLOBAL_DateCreated'), Obj.GLOBAL_DateCreated=datestr(now,SOFAdefinitions('dateFormat')); end +if isfield(Obj,'GLOBAL_APIVersion'), Obj.GLOBAL_APIVersion=SOFAgetVersion; end +if isfield(Obj,'GLOBAL_APIName'), Obj.GLOBAL_APIName=SOFAdefinitions('APIName'); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAgetVersion.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAgetVersion.m new file mode 100644 index 0000000000000000000000000000000000000000..4e449e4d01960950a9101f5ed6060b1e52b78234 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAgetVersion.m @@ -0,0 +1,26 @@ +function results = SOFAgetVersion(flag) +%SOFAGETVERSION +% version = SOFAgetVersion() returns the version of the SOFA API +% version = SOFAgetVersion('API') does the same. +% +% version = SOFAgetVersion('SOFA') returns the version of the SOFA +% supported by this API. + +% SOFA API - function SOFAgetVersion +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~exist('flag','var') + flag='API'; +end + +switch flag + case 'API' + results = '1.1.3'; + case 'SOFA' + results = '1.0'; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAinfo.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAinfo.m new file mode 100644 index 0000000000000000000000000000000000000000..ea2e8b0a2151f9ebf2cee8303fd067ae59a06a2a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAinfo.m @@ -0,0 +1,89 @@ +function SOFAinfo(Obj) +% SOFAinfo(Obj) gathers information about the SOFA object and display it. + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% Gather information about the SOFA file and display them + + + +switch Obj.GLOBAL_SOFAConventions +%% + case 'SimpleFreeFieldHRIR' + fprintf('\n'); + fprintf('%s\n',Obj.GLOBAL_Title); + fprintf('%s\n',repmat('=',1,length(Obj.GLOBAL_Title))); + fprintf('\n'); + fprintf('Anechoic HRTF mesurement done by %s.\n',Obj.GLOBAL_Organization); + fprintf('\n'); + fprintf('Contact: %s\n',Obj.GLOBAL_AuthorContact); + fprintf('License: %s\n',Obj.GLOBAL_License); + fprintf('URL: %s\n',Obj.GLOBAL_Origin); + fprintf('Reference: %s\n',Obj.GLOBAL_References); + fprintf('\n'); + fprintf('Measurement details:\n'); + fprintf('--------------------\n'); + fprintf('Number of azimuth angles: % 5.0f\n',length(unique(Obj.SourcePosition(:,1)))); + fprintf('Number of elevation angles: % 5.0f\n',length(unique(Obj.SourcePosition(:,2)))); + fprintf('Number of radii: % 5.0f\n',length(unique(Obj.SourcePosition(:,3)))); + if isfield(Obj.Data,'SamplingRate') + fprintf('Sampling Rate: %.0f %s\n',Obj.Data.SamplingRate,Obj.Data.SamplingRate_Units); + end + fprintf('Dummy head: %s\n',Obj.GLOBAL_ListenerShortName); + fprintf('Loudspeaker: %s\n',Obj.GLOBAL_SourceDescription); + if size(Obj.ListenerPosition,1)==1 + fprintf('Listener at (%.1f,%.1f,%.1f) %s\n', ... + Obj.ListenerPosition,Obj.ListenerPosition_Units); + else + fprintf(['%.0f listener positions from (%.1f,%.1f,%.1f) %s ', ... + 'to (%.1f,%.1f,%.1f) %s\n'],size(Obj.ListenerPosition,1), ... + Obj.ListenerPosition(1,:),Obj.ListenerPosition_Units, ... + Obj.ListenerPosition(end,:),Obj.ListenerPosition_Units); + end + if size(Obj.SourcePosition,1)==1 + fprintf('Source at (%.1f,%.1f,%.1f) %s\n', ... + Obj.SourcePosition,Obj.SourcePosition_Units); + else + fprintf(['%.0f source positions from (%.1f,%.1f,%.1f) %s ', ... + 'to (%.1f,%.1f,%.1f) %s\n'],size(Obj.SourcePosition,1), ... + Obj.SourcePosition(1,:),Obj.SourcePosition_Units, ... + Obj.SourcePosition(end,:),Obj.SourcePosition_Units); + end + fprintf('\n'); + +%% + otherwise + fprintf('\n'); + fprintf('%s\n',Obj.GLOBAL_Title); + fprintf('%s\n',repmat('=',1,length(Obj.GLOBAL_Title))); + fprintf('\n'); + fprintf('Mesurement done by %s.\n',Obj.GLOBAL_Organization); + fprintf('\n'); + fprintf('Contact: %s\n',Obj.GLOBAL_AuthorContact); + fprintf('License: %s\n',Obj.GLOBAL_License); + fprintf('URL: %s\n',Obj.GLOBAL_Origin); + fprintf('Reference: %s\n',Obj.GLOBAL_References); + fprintf('\n'); + fprintf('Measurement details:\n'); + fprintf('--------------------\n'); + fprintf('SOFA Convention: %s\n',Obj.GLOBAL_SOFAConventions); + % It is commented out by Atiyeh 01/08/2022 11:54 am + % fprintf('Listener: %s\n',Obj.GLOBAL_ListenerShortName); + % fprintf('Source: %s\n',Obj.GLOBAL_SourceDescription); + fprintf('Number of source positions: % 7.0f\n',size(unique(Obj.SourcePosition,'rows'),1)); + % fprintf('Number of source views: % 7.0f\n',size(unique(Obj.SourceView,'rows'),1)); + fprintf('Number of emitters: % 7.0f\n',size(unique(Obj.EmitterPosition,'rows'),1)); + fprintf('Number of listener positions: % 7.0f\n',size(unique(Obj.ListenerPosition,'rows'),1)); + % fprintf('Number of listener views: % 7.0f\n',size(unique(Obj.ListenerView,'rows'),1)); + fprintf('Number of receivers: % 7.0f\n',size(unique(Obj.ReceiverPosition,'rows'),1)); + if isfield(Obj.Data,'SamplingRate') + fprintf('Sampling Rate: %.0f %s\n',Obj.Data.SamplingRate,Obj.Data.SamplingRate_Units); + end + fprintf('\n'); + end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..a54d07c5f1bdc196ee011e1af2e7a02d3d6e85a0 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAload.m @@ -0,0 +1,192 @@ +function Obj = SOFAload(fn,varargin) +%SOFALOAD +% Obj = SOFAload(FN) reads the SOFA object OBJ with all data from +% a SOFA file FN. +% +% FN can point to a remote file (containing '://') or to a local file: +% Remote file: FN will be downloaded to a temporary directory and +% loaded. +% Local file: If existing, will be loaded. If not existing, it will be +% downloaded from the internet repository given by SOFAdbURL. For +% this, FN must begin with the local HRTF directory given by SOFAdbPath. +% +% Obj = SOFAload(FN,'nodata') ignores the "Data." variables and +% loads metadata only (variables and attributes). +% +% Obj = SOFAload(FN,[START COUNT]) loads only COUNT number of +% measurements (dimension M) beginning with the index START. For remote +% files, or local but not existing files, the full file will be downloaded. +% +% Obj = SOFAload(FN,[START1 COUNT1],DIM1,[START2 COUNT2],DIM2,...) loads +% only COUNT1 number of data in dimension DIM1 beginning with the index +% START1, COUNT2 number of data in dimension DIM2 with the index START2 +% and so on. +% +% Obj = SOFAload(FN,...,'nochecks') loads the file but does not perform +% any checks for correct conventions. +% + +% SOFA API - function SOFAload +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% ----- Input parameters ------------------------------------------------ +inputargs={}; % for setting flags with SOFAarghelper +pDims=''; % for partial loading +pDimRange=[]; % for partial loading +jj=1; kk=1; ll=1; +for ii=1:length(varargin) + if isnumeric(varargin{ii}) + pDimRange(jj,:)=varargin{ii}; + jj=jj+1; + if ii==1 + inputargs{kk}=varargin{ii}; + kk=kk+1; + end + elseif strfind('MREN',varargin{ii}) + pDims(ll)=varargin{ii}; + ll=ll+1; + elseif strcmp(varargin{ii},'nochecks') + inputargs{kk}=varargin{ii}; + elseif strcmp(varargin{ii},'nodata') + inputargs{kk}=varargin{ii}; + kk=kk+1; + end +end +if ~isempty(pDimRange) && isempty(pDims) + pDims='M'; +end + +% Set flags with SOFAarghelper +definput.keyvals.Index = []; +definput.flags.type = {'data','nodata'}; +definput.flags.data = {'checks','nochecks'}; +[flags,kv] = SOFAarghelper({'Index'},definput,inputargs); + +% Check number of input arguments for partial loading +if ~(length(pDims)==size(pDimRange,1) || isempty(kv.Index)) + error('Missing dimension or range for partial loading'); +end +% Check file name +fn = SOFAcheckFilename(fn); +% Check if local or remote and download if necessary +if strfind(fn,'://') + % remote path: download as temporary + newfn = [tempname '.sofa']; + urlwrite(fn, newfn); +else + newfn = fn; + if ~exist(fn,'file') % file does not exist? + warning('SOFA:load',['File not found: ' strrep(fn,'\','\\')]); + % local path: replace SOFAdbPath by SOFAdbURL, download to SOFAdbPath + if length(fn)>length(SOFAdbPath) % fn is longer than SOFAdbPath? + if strcmp(SOFAdbPath,fn(1:length(SOFAdbPath))) % fn begins with SOFAdbPath + % create dir if not existing + if ~exist(fileparts(newfn),'dir'), + [success,msg] = mkdir(fileparts(newfn)); + if success~=1, error(msg); end + end + webfn = fn(length(SOFAdbPath)+1:end); + webfn(strfind(webfn,'\'))='/'; + webfn = [SOFAdbURL regexprep(webfn,' ','%20')]; + disp(['Downloading ' fn(length(SOFAdbPath)+1:end) ' from ' SOFAdbURL]); + [f,stat] = urlwrite(webfn,fn); + if ~stat + error(['Could not download file: ' webfn]); + end + else % fn not existing and not beginning with SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + else % fn not existing and shorter than SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + end +end + + +%% ----- Load SOFA file -------------------------------------------------- +if flags.do_nodata + Obj = NETCDFload(newfn,'nodata'); +elseif flags.do_data + try + if isempty(kv.Index), + Obj = NETCDFload(newfn,'all'); + else + Obj = NETCDFload(newfn,pDimRange,pDims); + end + catch + error(['Error loading the file: ' newfn]); + end +end + + +%% ----- Checking of loaded data ----------------------------------------- +% Return if no checks should be performed +if flags.do_nochecks + return; +else + + % ----- Check for SOFA conventions ----- + if ~isfield(Obj,'GLOBAL_Conventions') || ~strcmp(Obj.GLOBAL_Conventions,'SOFA') + error('File is not a valid SOFA file'); + end + if ~isfield(Obj,'GLOBAL_SOFAConventions') + error('Information about SOFA conventions is missing'); + end + try + ObjTemplate = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + if isempty(ObjTemplate), + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + catch + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + + % ----- Check if DataType is present ----- + if ~isfield(Obj,'GLOBAL_DataType') + error('DataType is missing'); + end + + % ----- Check if mandatory variables are present ----- + for field = fieldnames(ObjTemplate)' + field = field{:}; + if ~isfield(Obj,field) + Obj.(field) = ObjTemplate.(field); + if ~strfind(field,'_') % if `_` is missing it is a dimension + Obj.API.Dimensions.(field) = ObjTemplate.API.Dimensions.(field); + end + warning('SOFA:load',[field ' was missing, set to default']); + end + end + + % ---- If data loaded, check for correct data format ----- + if ~flags.do_nodata + if ~isfield(Obj,'Data') + error('Data is missing'); + end + for field = fieldnames(ObjTemplate.Data)' + field = field{:}; + if ~isfield(Obj.Data,field) + Obj.Data.(field) = ObjTemplate.Data.(field); + Obj.API.Dimensions.Data.(field) = ... + ObjTemplate.API.Dimensions.Data.(field); + warning('SOFA:load',['Data.' field ' was missing, set to default']); + end + end + Obj = SOFAupdateDimensions(Obj); + end + + % ----- Ensure backwards compatibility ----- + % TODO: is the while loop necessary, or could be handled just by calling + % SOFAupgradeConventions(Obj) once? + modified = 1; + while modified + [Obj,modified] = SOFAupgradeConventions(Obj); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..fc0c2d1f42db683ef3fcf4d17be8d011f0ef7b68 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAmerge.m @@ -0,0 +1,151 @@ +function [C, log] = SOFAmerge(A,B) +%SOFAmerge +% [C, log] = SOFAmerge(A,B) merges the SOFA objects A and B to a single one, C. +% +% A and B are structs containing the data and meta. A and B +% must be of the same SOFA conventions. +% +% C is a struct containing merged data +% log contains log data + +% SOFA API - function SOFAupdateDimensions +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +if ~strcmp(A.GLOBAL_SOFAConventions,B.GLOBAL_SOFAConventions) + error('Both SOFA objects must use the same SOFA conventions'); +end +if A.API.N~=B.API.N + error('Data size of both SOFA objects must be the same'); +end +Def = SOFAdefinitions; +log={''}; +OC = SOFAgetConventions(A.GLOBAL_SOFAConventions,'a'); + +%% Update dimensions +A=SOFAupdateDimensions(A); +B=SOFAupdateDimensions(B); + +%% create field names which have to be checked +C=rmfield(B,{'API','Data'}); +if isfield(C,'PRIVATE'), C=rmfield(C,'PRIVATE'); end +Bf=fieldnames(C); + +%% Copy and merge metadata variables +C=A; +for ii=1:size(Bf,1) + if ~isfield(A,Bf{ii}) + C.(Bf{ii}) = B.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.(Bf{ii}),B.(Bf{ii})), + C.(Bf{ii}) = B.(Bf{ii}); % content the same, no conflict + else + switch Bf{ii} + case 'GLOBAL_TimeCreated' % use the oldest date + dateNew=datenum(A.GLOBAL_TimeCreated,Def.dateFormat); + if datenum(B.GLOBAL_TimeCreated,Def.dateFormat)<dateNew, dateNew=datenum(B.GLOBAL_TimeCreated,Def.dateFormat); end; + C.(Bf{ii}) = datestr(dateNew,Def.dateFormat); + log{end+1}=[Bf{ii} ' set to ' C.(Bf{ii})]; + case 'GLOBAL_TimeModified' % now + C.(Bf{ii}) = datestr(now,Def.dateFormat); + log{end+1}=[Bf{ii} ' updated']; + otherwise + C.(Bf{ii}) = [A.(Bf{ii}) '; ' B.(Bf{ii})]; % concatate [A; B] + log{end+1}=[Bf{ii} ' merged']; + end + end + else % a variable + if isfield(OC.API.Dimensions, Bf{ii}) % is a known variable? + AExp=SOFAexpand(A,Bf{ii}); + BExp=SOFAexpand(B,Bf{ii}); + dim=strfind(AExp.API.Dimensions.(Bf{ii}),'M'); + if isempty(dim), + error([Bf{ii} ' can not be merged because it does not depend on M']); + end + C.(Bf{ii})=cat(dim,AExp.(Bf{ii}),BExp.(Bf{ii})); + log{end+1}=[Bf{ii} ' expanded and merged']; + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.(Bf{ii}),'M'); + if ~isempty(dim), + C.(Bf{ii})=cat(dim,A.(Bf{ii}),B.(Bf{ii})); % depends on M, merge + log{end+1}=[Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.(Bf{ii})==B.(Bf{ii}))==1, + C.(Bf{ii})=A.(Bf{ii}); + log{end+1}=[Bf{ii} ' identical']; + else + error([Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Copy and merge Data variables +Bf=fieldnames(B.Data); +for ii=1:size(Bf,1) + if ~isfield(A.Data,Bf{ii}) + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.Data.(Bf{ii}),B.Data.(Bf{ii})), + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % content the same, no conflict + else + C.Data.(Bf{ii}) = [A.Data.(Bf{ii}) '; ' B.Data.(Bf{ii})]; % concatate [A; B] + log{end+1}=['Data.' Bf{ii} ' merged']; + end + else % a variable in Data + if isfield(OC.API.Dimensions.Data,Bf{ii}) % is a known variable? + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); % is a matrix + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if all(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Update the new dimensions and finish +C=SOFAcompact(C); +C=SOFAupdateDimensions(C); +if length(log)>1, log=log(2:end); else log={}; end; + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAplotGeometry.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAplotGeometry.m new file mode 100644 index 0000000000000000000000000000000000000000..2e0d96d5b05f62829350b7a76be438c707fcbc2b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAplotGeometry.m @@ -0,0 +1,181 @@ +function SOFAplotGeometry(Obj, index) +% SOFAplotGeometry(Obj) plots the geometry found in the Obj. +% +% SOFAplotGeometry(Obj, index) plots the geometry for the measurements +% given in the index. + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +if ~exist('index','var') + index=1:Obj.API.M; +end + +switch Obj.GLOBAL_SOFAConventions +%% + case {'SimpleFreeFieldHRIR','SingleRoomDRIR','SimpleFreeFieldTF','FreeFieldDirectivityTF'} + % Expand entries to the same number of measurement points + Obj = SOFAexpand(Obj); + % See if the room geometry is specified + if strcmp(Obj.GLOBAL_RoomType,'shoebox') + figure('Position',[1 1 (Obj.RoomCornerB(1)-Obj.RoomCornerA(1))*1.2 Obj.RoomCornerB(2)-Obj.RoomCornerA(2)]*100); + box on; hold on; h=[]; + % plot the room + rectangle('Position',[Obj.RoomCornerA(1) ... + Obj.RoomCornerA(2) ... + Obj.RoomCornerB(1)-Obj.RoomCornerA(1) ... + Obj.RoomCornerB(2)-Obj.RoomCornerA(2)]); + else + figure; hold on; + end + legendEntries = []; + title(sprintf('%s, %s',Obj.GLOBAL_SOFAConventions,Obj.GLOBAL_RoomType)); + % Get ListenerPosition, ListenerView, ReceiverPosition, and SourcePosition + % NOTE: ListenerPosition is set to [0 0 0] for SimpleFreeFieldHRIR + LP = SOFAconvertCoordinates(Obj.ListenerPosition(index,:),Obj.ListenerPosition_Type,'cartesian'); + if isfield(Obj,'ListenerView') + LV = SOFAconvertCoordinates(Obj.ListenerView(index,:),Obj.ListenerView_Type,'cartesian'); + else + LV = repmat([1 0 0],size(LP,1),1); + end + RP = SOFAconvertCoordinates(Obj.ReceiverPosition(:,:,index),Obj.ReceiverPosition_Type,'cartesian'); + if strcmp(Obj.SourcePosition_Type,'cartesian') + SP=Obj.SourcePosition(index,:); + else + SP = SOFAconvertCoordinates(Obj.SourcePosition(index,:),Obj.SourcePosition_Type,'cartesian'); + end + if isfield(Obj,'SourceView') + if strcmp(Obj.SourceView_Type,'cartesian') + SV=Obj.SourceView(index,:); + else + SV = SOFAconvertCoordinates(Obj.SourceView(index,:),Obj.SourceView_Type,'cartesian'); + end + else + SV = zeros(size(LP)); % if SourceView not given, source is omnidirectional + end + % Use only unique listener and source positons + uniquePoints = unique([LP LV SP SV],'rows'); + LP = uniquePoints(:,1:3); + LV = uniquePoints(:,4:6); + SP = uniquePoints(:,7:9); + SV = uniquePoints(:,10:12); + % Plot ListenerPosition + legendEntries(end+1) = plot3(LP(:,1),LP(:,2),LP(:,3),'ro','MarkerFaceColor',[1 0 0]); + % Plot ListenerView + for ii=1:size(LV,1) + % Scale size of ListenerView vector smaller + LV(ii,:) = 0.2*LV(ii,:)./norm(LV(ii,:)); + % Plot line for ListenerView vector + line([LP(ii,1), LV(ii,1)+LP(ii,1)], [LP(ii,2) LV(ii,2)+LP(ii,2)], 'Color',[1 0 0]); + end + legendEntries(end+1) = plot3(LV(:,1)+LP(:,1),LV(:,2)+LP(:,2),LV(:,3)+LP(:,3),'ro','MarkerFaceColor',[1 1 1]); + % Plot ReceiverPositon (this is plotted only for the first ListenerPosition) + if ndims(RP)>2 + % If ReceiverPosition has more than two dimensions reduce it to the first + % ListenerPosition + RP = shiftdim(RP,2); + RP = squeeze(RP(1,:,:)); + end + legendEntries(end+1) = plot3(LP(1,1)+RP(1,1), LP(1,2)+RP(1,2), LP(1,3)+RP(1,3),'rx'); + for ii=2:size(RP,1) + plot3(LP(1,1)+RP(ii,1), LP(1,2)+RP(ii,2), LP(1,3)+RP(ii,3),'rx'); + end + % Plot SourcePosition + legendEntries(end+1)=plot3(SP(:,1),SP(:,2),SP(:,3),'ks','MarkerFaceColor',[0 0 0]); + % Plot SourceView + for ii=1:size(SV,1) + % Scale size of SourceView vector smaller + SV(ii,:) = 0.2*SV(ii,:)./norm(SV(ii,:)); + % Plot line for SourceView vector + line([SP(ii,1), SV(ii,1)+SP(ii,1)], [SP(ii,2) SV(ii,2)+SP(ii,2)], 'Color',[0 0 0]); + end + legendEntries(end+1) = plot3(SV(:,1)+SP(:,1),SV(:,2)+SP(:,2),SV(:,3)+SP(:,3),'ks','MarkerFaceColor',[1 1 1]); + % create legend + legend(legendEntries,{'ListenerPosition','ListenerView','Receivers','SourcePosition','SourceView'},'Location','NorthEastOutside'); + xlabel(['X / ' Obj.ListenerPosition_Units]); + ylabel(['Y / ' Obj.ListenerPosition_Units]); + zlabel(['Z / ' Obj.ListenerPosition_Units]); + + case {'GeneralFIR'} + % Expand entries to the same number of measurement points + ObjC=Obj; % save as compact object + Obj = SOFAexpand(Obj); + % See if the room geometry is specified + if strcmp(Obj.GLOBAL_RoomType,'shoebox') + figure('Position',[1 1 (Obj.RoomCornerB(1)-Obj.RoomCornerA(1))*1.2 Obj.RoomCornerB(2)-Obj.RoomCornerA(2)]*100); + box on; hold on; h=[]; + % plot the room + rectangle('Position',[Obj.RoomCornerA(1) ... + Obj.RoomCornerA(2) ... + Obj.RoomCornerB(1)-Obj.RoomCornerA(1) ... + Obj.RoomCornerB(2)-Obj.RoomCornerA(2)]); + else + figure; hold on; + end + legendEntries = []; + title(sprintf('%s, %s',Obj.GLOBAL_SOFAConventions,Obj.GLOBAL_RoomType)); + % Get ListenerPosition, ListenerView, ReceiverPosition, and SourcePosition + % NOTE: ListenerPosition is set to [0 0 0] for SimpleFreeFieldHRIR + LP = SOFAconvertCoordinates(Obj.ListenerPosition(index,:),Obj.ListenerPosition_Type,'cartesian'); + if isfield(Obj,'ListenerView') + LV = SOFAconvertCoordinates(Obj.ListenerView(index,:),Obj.ListenerView_Type,'cartesian'); + else + LV = repmat([1 0 0],size(LP,1),1); + end + if strcmp(Obj.SourcePosition_Type,'cartesian') + SP=Obj.SourcePosition(index,:); + else + SP = SOFAconvertCoordinates(Obj.SourcePosition(index,:),Obj.SourcePosition_Type,'cartesian'); + end + % Use only unique listener and source positons + uniquePoints = unique([LP LV SP],'rows'); + LP = uniquePoints(:,1:3); + LV = uniquePoints(:,4:6); + SP = uniquePoints(:,7:9); + % Plot ListenerPosition + legendEntries(end+1) = plot3(LP(:,1),LP(:,2),LP(:,3),'ro','MarkerFaceColor',[1 0 0]); + % Plot ListenerView + for ii=1:size(LV,1) + % Scale size of ListenerView vector smaller + LV(ii,:) = 0.2*LV(ii,:)./norm(LV(ii,:)); + % Plot line for ListenerView vector + line([LP(ii,1), LV(ii,1)+LP(ii,1)], [LP(ii,2) LV(ii,2)+LP(ii,2)], 'Color',[1 0 0]); + end + legendEntries(end+1) = plot3(LV(:,1)+LP(:,1),LV(:,2)+LP(:,2),LV(:,3)+LP(:,3),'ro','MarkerFaceColor',[1 1 1]); + % Plot ReceiverPositon (this is plotted only for the first ListenerPosition) + RP = SOFAconvertCoordinates(ObjC.ReceiverPosition(:,:,:),ObjC.ReceiverPosition_Type,'cartesian'); + if ndims(RP)>2 + % If ReceiverPosition has more than two dimensions reduce it to the first + % ListenerPosition + RP = shiftdim(RP,2); + RP = unique(RP); + RP = squeeze(RP(1,:,:)); + end + legendEntries(end+1) = plot3(LP(1,1)+RP(1,1), LP(1,2)+RP(1,2), LP(1,3)+RP(1,3),'rx'); + for ii=2:size(RP,1) + plot3(LP(1,1)+RP(ii,1), LP(1,2)+RP(ii,2), LP(1,3)+RP(ii,3),'rx'); + end + % Plot SourcePosition + legendEntries(end+1)=plot3(SP(:,1),SP(:,2),SP(:,3),'k.'); + legend(legendEntries,{'ListenerPosition','ListenerView','Receivers','SourcePosition'},'Location','NorthEastOutside'); + xlabel(['X / ' Obj.ListenerPosition_Units]); + ylabel(['Y / ' Obj.ListenerPosition_Units]); + zlabel(['Z / ' Obj.ListenerPosition_Units]); + + otherwise + error('This SOFAConventions is not supported for plotting'); +end + +% Set fixed aspect ratio +axis equal; +% Add a little bit extra space at the axis +axisLimits = axis(); +paddingSpace = 0.2 * max(abs(axisLimits(:))); +axisLimits([1 3]) = axisLimits([1 3]) - paddingSpace; +axisLimits([2 4]) = axisLimits([2 4]) + paddingSpace; +axis(axisLimits); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..1c7e9406bed40bd3a7f4dcb182cbdb1ad08df1e7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAplotHRTF.m @@ -0,0 +1,362 @@ +function [M,meta,h]=SOFAplotHRTF(Obj,type,varargin) +% SOFAplotHRTF(OBJ, TYPE, CH, DIR, COLOR) plots the CH channel of HRTFs given in OBJ. +% The following TYPEs are supported: +% 'EtcHorizontal' energy-time curve in the horizontal plane (+/- THR) +% 'EtcMedian' energy-time curve in the median plane (+/- THR) +% 'MagHorizontal' magnitude spectra in the horizontal plane (+/- THR) +% 'MagMedian' magnitude spectra in the median plane (+/- THR) +% 'magspectrum' single magnitude spectrum for direction(s) DIR in COLOR +% 'MagSagittal' magnitude spectra in a sagittal plane specified by OFFSET +/- THR +% +% More options are available by SOFAplotHRTF(Obj,type,parameter,value) +% +% Parameter +% 'ch' receiver channel to be plotted. Default: 1 +% 'dir' fixes the positions to be plotted: +% [azi]: shows all direction for that azimuth +% [azi, ele]: shows all distances for that direction +% [azi, ele, distance]: shows only that position +% default: [0,0] +% 'offset' chooses a plane to be plotted. Default: 0 deg. +% 'thr' threshold for selecting positions around a plane. Default: 2 deg. +% 'color' color for plotting as used by PLOT +% +% +% Supported conventions: +% SimpleFreeFieldHRIR +% SimpleFreeFieldSOS +% SimpleFreeFieldTF +% some special cases of GeneralTF. +% +% [M,meta,h]=SOFAplotHRTF... returns the matrix M and axes (meta) displayed in the figure. +% h is the handle of the plot. +% + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% for backward compatibility (type as position-dependent input parameter) +if nargin == 3 && ischar(type) && isscalar(varargin{1}) +% varargin = flipud(varargin(:)); + ch = varargin{1}; + flags.do_normalize=1; + dir=[0,0]; + color='b'; + thr=2; + offset=0; +else + definput.keyvals.ch=1; + definput.keyvals.dir=[0,0]; + definput.keyvals.thr=2; + definput.keyvals.offset=0; + definput.flags.color={'b','r','k','y','g','c','m'}; + definput.flags.level={'normalize','absolute'}; + argin=varargin; + for ii=1:length(argin) + if ischar(argin{ii}), argin{ii}=lower(argin{ii}); end + end + [flags,kv] = SOFAarghelper({'ch','dir','thr','offset'},definput,argin); + ch = kv.ch; + dir = kv.dir; + thr=kv.thr; + color = flags.color; + offset = kv.offset; +end +M=[]; +meta=[]; + +%% Convert data to FIR +switch Obj.GLOBAL_SOFAConventions + case 'SimpleFreeFieldSOS' + N=512; + impulse=[1; zeros(N-1,1)]; + T=SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_SOFAConventions=T.GLOBAL_SOFAConventions; + Obj.GLOBAL_SOFAConventionsVersion=T.GLOBAL_SOFAConventionsVersion; + Obj.GLOBAL_DataType=T.GLOBAL_DataType; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + Obj.Data.IR(ii,jj,:)=sosfilt(reshape(squeeze(Obj.Data.SOS(ii,jj,:)),6,[])',impulse); + end + end + Obj.Data=rmfield(Obj.Data,'SOS'); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + Obj=SOFAupdateDimensions(Obj); + case {'SimpleFreeFieldTF' 'GeneralTF'} + if sum(diff(diff(Obj.N))) + fs=max(Obj.N)*2; % irregular grid, find the smallest frequency difference + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + Nidx=Obj.N*N/fs+1; + Nsize=floor(N/2+1); + else + N=2*(length(Obj.N)-1); % regular grid (from an DFT probably), works for odd length only + fs=max(Obj.N)*2; + Nidx=1:length(Obj.N); + Nsize=length(Obj.N); + end + T=SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_SOFAConventions=T.GLOBAL_SOFAConventions; + Obj.GLOBAL_SOFAConventionsVersion=T.GLOBAL_SOFAConventionsVersion; + Obj.GLOBAL_DataType=T.GLOBAL_DataType; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=fs; + Obj.Data.SamplingRate_Units='Hertz'; + Obj.Data.IR_LongName=Obj.Data.Real_LongName; + Obj.Data.IR_Units=Obj.Data.Real_Units; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(Nsize,1); + s(Nidx)=squeeze(Obj.Data.Real(ii,jj,:))+1i*squeeze(Obj.Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,T.SourcePosition_Type,Obj.SourcePosition_Units,T.SourcePosition_Units); + end + Obj.Data.Delay=zeros(1,Obj.API.R); + Obj.SourcePosition_Type=T.SourcePosition_Type; + Obj.SourcePosition_Units=T.SourcePosition_Units; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag','Real_LongName','Imag_LongName','Real_Units','Imag_Units'}); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + Obj=SOFAupdateDimensions(Obj); + case {'SimpleFreeFieldHRIR','GeneralFIR'} + otherwise + error('Conventions not supported'); +end + +fs=Obj.Data.SamplingRate; +%% Convert to spherical if cartesian +if strcmp(Obj.SourcePosition_Type,'cartesian') + for ii=1:Obj.API.M + [Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)]=cart2sph(Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)); + Obj.SourcePosition(ii,2)=rad2deg(Obj.SourcePosition(ii,2)); + Obj.SourcePosition(ii,1)=rad2deg(Obj.SourcePosition(ii,1)); + Obj.SourcePosition(ii,1)=npi2pi(Obj.SourcePosition(ii,1),'degrees'); + end + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degrees'; +end + +%% Plot according to the type +switch lower(type) + % Energy-time curve (ETC) in the horizontal plane + case 'etchorizontal' + noisefloor=-50; + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,ch,:))); + pos=Obj.SourcePosition; + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,ch)); + M2=noisefloor*ones(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + [azi,i]=sort(pos(:,1)); + M=M2(i,:); + if flags.do_normalize + M=M-max(max(M)); + end + M(M<=noisefloor)=noisefloor; + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.azi = azi; + h=surface(meta.time,azi,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Azimuth (deg)'); + title([Obj.GLOBAL_Title '; channel: ' num2str(ch)],'Interpreter','none'); + + % Magnitude spectrum in the horizontal plane + case 'maghorizontal' + noisefloor=-50; + hM=double(squeeze(Obj.Data.IR(:,ch,:))); + pos=Obj.SourcePosition; + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); +% idx=find(abs(pos(:,1))>90); +% pos(idx,2)=180-pos(idx,2); +% pos(idx,1)=180-pos(idx,1); +% idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + pos=pos(idx,:); + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [azi,i]=sort(pos(:,1)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.azi = azi; + h=surface(meta.freq,azi,M(:,:)); + shading flat + xlabel('Frequency (Hz)'); + ylabel('Azimuth (deg)'); + title([Obj.GLOBAL_Title '; channel: ' num2str(ch)],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magmedian' + noisefloor=-50; + azi=0; + hM=double(squeeze(Obj.Data.IR(:,ch,:))); + pos=Obj.SourcePosition; + idx=find(abs(pos(:,1))>90); + pos(idx,2)=180-pos(idx,2); + pos(idx,1)=180-pos(idx,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + pos=pos(idx,:); + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + h=surface(meta.freq,ele,M(:,:)); + shading flat + xlabel('Frequency (Hz)'); + ylabel('Elevation (deg)'); + title([Obj.GLOBAL_Title '; channel: ' num2str(ch)],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magsagittal' + noisefloor=-50; + hM=double(squeeze(Obj.Data.IR(:,ch,:))); + [lat,pol]=sph2hor(Obj.SourcePosition(:,1),Obj.SourcePosition(:,2)); + pos=[lat pol]; +% idx=find(abs(pos(:,1))>90); +% pos(idx,2)=180-pos(idx,2); +% pos(idx,1)=180-pos(idx,1); + idx=find(pos(:,1)<(offset+thr) & pos(:,1)>(offset-thr)); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + pos=pos(idx,:); + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + h=surface(meta.freq,ele,M(:,:)); + shading flat + xlabel('Frequency (Hz)'); + ylabel('Polar angle (deg)'); + title([Obj.GLOBAL_Title '; channel: ' num2str(ch) '; Lateral angle: ' num2str(offset) 'deg'],'Interpreter','none'); + + + % ETC in the median plane + case 'etcmedian' + noisefloor=-50; + azi=0; + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,ch,:))); + pos=Obj.SourcePosition; + idx=find(abs(pos(:,1))>90); + pos(idx,2)=180-pos(idx,2); + pos(idx,1)=180-pos(idx,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,ch)); + M2=zeros(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + if flags.do_normalize + M=M2-max(max(M2)); + else + M = M2; + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.ele = ele; + h=surface(meta.time,ele,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Elevation (deg)'); + title([Obj.GLOBAL_Title '; channel: ' num2str(ch)],'Interpreter','none'); + + case 'magspectrum' + noisefloor=-50; + pos=round(Obj.SourcePosition,1); + switch length(dir) + case 1 + idx=find(pos(:,1)==dir(:,1)); + case 2 + idx=find(pos(:,1)==dir(:,1) & pos(:,2)==dir(:,2)); + otherwise + idx=find(pos(:,1)==dir(:,1) & pos(:,2)==dir(:,2) & pos(:,3)==dir(:,3)); + end + if isempty(idx), error('Position not found'); end + IR=squeeze(Obj.Data.IR(idx,ch,:)); + + if length(idx) > 1, + M=20*log10(abs(fft(IR')))'; + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + h=plot(0:fs/2/size(M,2):(size(M,2)-1)*fs/2/size(M,2),M); + for ii=1:length(idx) + labels{ii}=['#' num2str(idx(ii)) ': (' num2str(pos(idx(ii),1)) ', ' num2str(pos(idx(ii),2)) ')']; + end + legend(labels); + else + hM=20*log10(abs(fft(IR))); + M=hM(1:floor(length(hM)/2)); + hold on; + h=plot(0:fs/2/length(hM):(length(M)-1)*fs/2/length(hM),M,color,... + 'DisplayName',['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + leg=legend; + if isempty(leg), + legend(['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + else + leg=leg.String; + leg{end+1}=['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']; + legend('off'); + legend(leg); + end + end + ylabel('Magnitude (dB)'); + xlabel('Frequency (Hz)'); + ylim([max(max(M))+noisefloor-10 max(max(M))+10]); + xlim([0 fs/2]); +end + + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end; +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAremoveVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAremoveVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..0e4c32f4ebd7296df6265dc2387377f16cf17157 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAremoveVariable.m @@ -0,0 +1,31 @@ +function Obj = SOFAremoveVariable(Obj,Name) +%SOFAremoveVariable +% Obj = SOFAremoveVariable(Obj,Name) removes the user-defined variable +% from the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). +% +% + +% 19.6.2019: adapted from SOFAaddVariable (PM) +% +% SOFA API - function SOFAremoveVariable +% Copyright (C) 2012-2019 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +switch Name + case {'API','PRIVATE','GLOBAL','PRIVATE','Data'} + error('This variable name is reserved.'); + otherwise + if isfield(Obj,Name) + Obj=rmfield(Obj,Name); + if isfield(Obj.API.Dimensions,Name) + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,Name); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..32a4440b8b43e2648ab731b037428e78cedc2bb7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAsave.m @@ -0,0 +1,93 @@ +function [Obj] = SOFAsave(filename,Obj,varargin) +%SOFASAVE +% [] = SOFAsave(filename,Obj,Compression) creates a new SOFA file and +% writes an entire data set to it. +% +% filename specifies the name of the SOFA file to which the data is written. +% Obj is a struct containing the data and meta +% data to be written to the SOFA file (see below for exact format). +% Compression is an optional numeric value between 0 and 9 specifying the +% amount of compression to be applied to the data when writing to the netCDF file. +% 0 is no compression and 9 is the most compression. +% +% The existence of mandatory variables will be checked. The dimensions +% will be updated. + +% SOFA API - function SOFAsave +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Def = SOFAdefinitions; + +%% check file name +filename=SOFAcheckFilename(filename); + +%% Remove private data +if isfield(Obj,'PRIVATE'), Obj=rmfield(Obj,'PRIVATE'); end + +%% Check convention: mandatory variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + +varNames = fieldnames(ObjCheck); +for ii=1:size(varNames,1); + if ~isfield(Obj,varNames{ii}) + error(['Mandatory variable/attribute not existing: ' varNames{ii}]); + end +end + +%% Get & set dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Check convention: read-only variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'r'); +varNames = fieldnames(ObjCheck); + +for ii=1:size(varNames,1); + if ischar(Obj.(varNames{ii})) + if ~strcmp(Obj.(varNames{ii}), ObjCheck.(varNames{ii})) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + else + if Obj.(varNames{ii}) ~= ObjCheck.(varNames{ii}) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + end +end + +%% check attributes (syntax, 1-dimensional string) +varNames = fieldnames(Obj); +for ii=1:size(varNames,1); + + if size(strfind(varNames{ii},'_'),2) == 1 + if ~ischar(Obj.(varNames{ii})) + error(['Attribute not a valid string: ' varNames{ii} ' = ' num2str(Obj.(varNames{ii}))]); + end + elseif size(strfind(varNames{ii},'_'),2) > 1 + error(['Attribute not valid (only one underscore "_" is allowed in attribute name): ' varNames{ii}]); + end + +end + +%% check varargin (compression) +if ~isempty(varargin) && isnumeric(varargin{1}) + if isscalar(varargin{1}) && varargin{1}>=0 && varargin{1}<=9 + Compression = varargin{1}; + else + error('Error: Compression must be a numeric scalar value between 0 and 9.'); + end +else + Compression = 1; % default +end + +%% Set/modify time information +Obj.GLOBAL_DateModified=datestr(now,Def.dateFormat); +if isempty(Obj.GLOBAL_DateCreated), Obj.GLOBAL_DateCreated=Obj.GLOBAL_DateModified; end + +%% Save file +NETCDFsave(filename,Obj,Compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..d1986500fd94b61f44358544a09a84d51cb8a0b5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAspat.m @@ -0,0 +1,110 @@ +function [out, azi, ele, idx] = SOFAspat(in,Obj,azi,ele) +% SOFAspat +% [out, azi, ele, idx] = SOFAspat(in,Obj,azi,ele) spatializes the sound IN using +% the HRTFs from OBJ according to the trajectory given in AZI and ELE. +% Input: +% in: vector with the sound +% Obj: SOFA object containing the HRTFs +% azi, ele: vectors with the trajectory (in degrees) independent for +% azimuth and elevation +% +% Output: +% out: binaural signal +% azi, ele: azimuth and elevation of the actual trajectory (degrees) +% idx: index of the filters (corresponds to AZI and ELE) +% +% This is an example of how to use SOFA. +% +% Piotr Majdak, 2013 +% adapted by Robert Baumgartner, 2016 + +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define required parameters +hop=0.5; % the hop size for the time-variant filtering (in fraction of the filter length) + +%% Initial checks +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + error('HRTFs must be saved in the SOFA conventions SimpleFreeFieldHRIR'); +end +if min(azi)<0, % Check for the required coordinate system + Obj.SourcePosition(:,1)=sph2nav(Obj.SourcePosition(:,1)); % if negative azimuths are required, swith to -90/+90 system +end +N=Obj.API.N; + +%% resize the input signal to be integer multiple of HRIR +L=length(in); +in=[in; zeros(N-mod(L,N),1)]; +L=length(in); % correct length of the input signal +S=L/N/hop; % number of segments to filter + +%% Resample the trajectory +if length(azi)>1, + azi= interp1(0:1/(length(azi)-1):1,azi,0:1/(S-1):1); +else + azi=repmat(azi,1,S); +end; +if length(ele)>1, + ele= interp1(0:1/(length(ele)-1):1,ele,0:1/(S-1):1); +else + ele=repmat(ele,1,S); +end; + +%% create a 2D-grid with nearest positions of the moving source +idx=zeros(S,1); +[target.x,target.y,target.z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(1,S)); +[pos.x,pos.y,pos.z] = sph2cart(deg2rad(Obj.SourcePosition(:,1)),... + deg2rad(Obj.SourcePosition(:,2)),Obj.SourcePosition(:,3)); +for ii=1:S % find nearest point on grid (LSP) + dist = (pos.x-target.x(ii)).^2 + (pos.y-target.y(ii)).^2 + (pos.z-target.z(ii)).^2; + [~,idx(ii)]=min(dist); +end + +%% normalize HRTFs to the frontal, eye-level position +% ii=find(Obj.SourcePosition(:,1)==0 & Obj.SourcePosition(:,2)==0); % search for position 0�/0� +% if isempty(ii) +% peak=max([sqrt(sum(Obj.Data.IR(:,1,:).*Obj.Data.IR(:,1,:))) sqrt(sum(Obj.Data.IR(:,2,:).*Obj.Data.IR(:,2,:)))]); % not found - normalize to IR with most energy +% else +% peak=([sqrt(sum(Obj.Data.IR(ii,1,:).*Obj.Data.IR(ii,1,:))) sqrt(sum(Obj.Data.IR(ii,2,:).*Obj.Data.IR(ii,2,:)))]); % found - normalize to this position +% end + +%% Spatialize +out=zeros(L+N/hop,2); +window=hanning(N); +ii=0; +jj=1; +iiend=L-N; +while ii<iiend + segT=in(ii+1:ii+N).*window; % segment in time domain + segF=fft(segT,2*N); % segment in frequency domain with zero padding + %----------- + segFO(:,1)=squeeze(fft(Obj.Data.IR(idx(jj),1,:),2*N)).*segF; + segFO(:,2)=squeeze(fft(Obj.Data.IR(idx(jj),2,:),2*N)).*segF; + %----------- + segTO=real(ifft(segFO)); % back to the time domain + out(ii+1:ii+2*N,:)=out(ii+1:ii+2*N,:)+segTO; % overlap and add + ii=ii+N*hop; + jj=jj+1; +end + +%% Normalize +% out(:,1)=out(:,1)/peak(1); +% out(:,2)=out(:,2)/peak(2); + +%% Output +% actually used angles +azi = Obj.SourcePosition(idx,1); +ele = Obj.SourcePosition(idx,2); +% upsampled for each sample +idup = floor(1:1/(N*hop):S+1-1/(N*hop)); +azi = azi(idup); +ele = ele(idup); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAstart.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAstart.m new file mode 100644 index 0000000000000000000000000000000000000000..226c09129f27bd7450a7e6264839c253c64b0a42 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAstart.m @@ -0,0 +1,105 @@ +function SOFAstart(flags) +% SOFAstart +% +% SOFAstart adds all needed pathes and checks if we need the Matlab or Octave +% version of the API +% +% SOFAstart(0) or SOFAstart('silent') will suppress any message during the start. +% SOFAstart ('short') will show a short header only during the start. +% +% SOFAstart checks if SOFA has been started within the MATLAB session. If +% it is the case, SOFAstart skips all the initialization. If the initialization +% is required, SOFA('restart') performs the initialization in any case. +% + +% SOFA API - function SOFAstart +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Input parameters +verbose = 2; +restart = 0; +if nargin>0 + if strcmp(lower(flags),'silent'), verbose=0; end; + if strcmp(lower(flags),'short'), verbose=1; end; + if isnumeric(flags), if flags==0, verbose=0; end; end; + if strcmp(lower(flags),'restart'), restart=1; end +end + +%% do not start when already started but not forced to restart +persistent started +if ~isempty(started) && ~restart, + return; +end +started=1; +%% Check required support +if exist('OCTAVE_VERSION','builtin') + % We're in Octave + if compare_versions(OCTAVE_VERSION,'3.6.0','<=') % check if the octave version is high enough + error('You need Octave >=3.6.0 to work with SOFA.'); + end + pkg load netcdf + if ~which('test_netcdf') % check if octcdf is installed + error('You have to install the netcdf package in Octave to work with SOFA.'); + end +else + % We're in Matlab + if verLessThan('matlab','8') + warning('SOFA:start','SOFA for Matlab version <= 8 (2012b) not tested. Use on your risk.'); + end +end + + +%% Add Paths +% Get the basepath as the directory this function resides in. +% The 'which' solution below is more portable than 'mfilename' +% becase old versions of Matlab does not have "mfilename('fullpath')" +basepath=which('SOFAstart'); +basepath=basepath(1:end-12); % Kill the function name from the path. +f=filesep; +% Add the base path and the needed sub-directories +if exist('addpath','builtin') + addpath(basepath); + addpath([basepath f 'helper']); + addpath([basepath f 'coordinates']); + addpath([basepath f 'converters']); + addpath([basepath f 'demos']); + addpath([basepath f 'netcdf']); +else + path(path,basepath); + path(path,[basepath f 'helper']); + path(path,[basepath f 'coordinates']); + path(path,[basepath f 'converters']); + path(path,[basepath f 'demos']); + path(path,[basepath f 'netcdf']); +end + +% Provide SOFA conventions +SOFAcompileConventions; +convs=SOFAgetConventions; + +%% Display general informations +if verbose + disp(['SOFA Matlab/Octave API version ' SOFAgetVersion '. Copyright 2013 Acoustics Research Institute (piotr@majdak.com).']); + if verbose==2, + disp(['This API implements SOFA version ' SOFAgetVersion('SOFA') '.']); + text=['Available SOFA Conventions: ' convs{1}]; + for ii=2:length(convs) + text=[text ', ' convs{ii}]; + end + disp(text); + disp(['SOFAdbPath (local HRTF database): ' SOFAdbPath ]); + disp(['SOFAdbURL (internet repository): ' SOFAdbURL]); + end +end + +% FIXME: I would check only if the URL is available in the function where it is +% needed. At the start it takes to long. Octaves urlread didn't know the TimeOut +% parameter. +%[~,stat]=urlread(SOFAdbURL); +%if ~stat, disp(' --> could not connect'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAupdateDimensions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAupdateDimensions.m new file mode 100644 index 0000000000000000000000000000000000000000..94c0b961ae86d8c8d8a78360028af0a089e004db --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAupdateDimensions.m @@ -0,0 +1,162 @@ +function Obj = SOFAupdateDimensions(Obj,varargin) +%SOFAupdateDimensions +% Obj = SOFAupdateDimensions(Obj) updates the dimensions in the SOFA +% structure +% +% Obj is a struct containing the data and meta. +% The dimension sizes are created as .API.X and updated corresponding to the +% conventions +% flag is 'nodata' or 'all'; default is 'all' + +% 9.8.2014: String support added. +% +% SOFA API - function SOFAupdateDimensions +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.keyvals.Index=[]; +definput.flags.type={'data','nodata'}; +[flags,kv]=SOFAarghelper({'Index'},definput,varargin); + +%% Get conventions with allowed dimensions +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); + +%% Add dimensions if required +dims=fieldnames(SOFAdefinitions('dimensions')); +for ii=1:size(dims,1) + if ~isfield(Obj.API,dims{ii}), Obj.API.(dims{ii})=0; end +end + +%% Update dimension sizes from the variables having dominant dimensions sizes + % fix dimension sizes +Obj.API.I=1; +Obj.API.C=3; + % check all metadata variables for dominant dimension sizes +dims='renm'; +f=fieldnames(rmfield(OC.API.Dimensions,'Data')); +for ii=1:length(dims) + for jj=1:length(f) + dim=strfind(OC.API.Dimensions.(f{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(f{jj}),dim(1)); + break; + end + end +end +% check all data variables +if flags.do_data + fd=fieldnames(OC.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fd) + dim=strfind(OC.API.Dimensions.Data.(fd{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fd{jj}),dim(1)); + break; + end + end + end +end + +%% Update the dimensions of metadata variables +Smax=0; +X=rmfield(Obj,{'Data','API'}); +if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end +Xf=fieldnames(X); +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions, Xf{ii}), % is a known variable +% disp(Xf{ii}); + dim=OC.API.Dimensions.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.(Xf{ii})=dim; + end + else % is a user-defined variable + if ~isfield(Obj.API.Dimensions,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without a dimension.']); + else + dim=Obj.API.Dimensions.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension does not match.']); + end + end + end + Smax=max(Smax,S); + end +end +%% Update the dimensions of data variables +if flags.do_data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions.Data, Xf{ii}), % is a known variable + dim=OC.API.Dimensions.Data.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.Data.(Xf{ii})=dim; + end + Smax=max(Smax,S); + else + if ~isfield(Obj.API.Dimensions.Data,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without a dimension.']); + else + dim=Obj.API.Dimensions.Data.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension does not match.']); + end + end + end + end + end +end +%% Update the size of the longest string +if Smax>0, Obj.API.S=Smax; end + +%% Return the size of x. If x is a cell, return the size of the strings in x. +function s=sizecell(x,dim) +if iscell(x) + s=size(char(x)); + if size(x,1)~=s(1) s=[size(x) s(2)]; end % multidim cellarays: s = [celldim1, celldim2, ... , celldimN, stringdim] +else + s=size(x); +end + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.(f)),upper(str)); + +%% dims is a cell array with allowed dimensions. +% S is the size of the string dimension. S=0 when S does not exist +% dimA is a vector with the actual dimensions. +% dim is a string with the matching dimension +function [dim,S]=checkdim(Obj,dims,dimA) +dim=[]; S=0; +for jj=1:length(dims) + dimS=dims{jj}; + if length(dimS)==1, dimS=[dimS 'I']; end; % 1D required, but Matlab is always 2D at least. + dimR=getdim(Obj.API,dimS); + if length(dimA)==length(dimR), % the same size? + if ~isempty(strfind(dimS,'S')) + Sidx=strfind(dimS,'S'); + S=max(S,dimA(Sidx)); + dimR(Sidx)=dimA(Sidx); % string dim are always correct + end + if dimA==dimR, dim=upper(dims{jj}); break; end; % found! + elseif length(dimA)<length(dimR) % extend the size? + if [dimA ones(1,length(dimR)-length(dimA))]==dimR, dim=upper(dims{jj}); break; end; % found! + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAupgradeConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAupgradeConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..6256602d7c012f5ed8c85b1618f3e55321e6ebec --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/SOFAupgradeConventions.m @@ -0,0 +1,172 @@ +function [Obj,modified] = SOFAupgradeConventions(Obj) +%SOFAcompatibility +% [Obj,modified] = SOFAupgradeConventions(Obj) upgrades the Obj to the next higher +% version if required. MODIFIED is 1 when an upgrade was required. +% In order to obtain the most recent version, SOFAupgradeConventions +% should be processed recursively until MODIFIED is 0. + + +% SOFA API - function SOFAcompatibility +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +modified=0; + +%% Upgrade specific to a SOFA version + +switch Obj.GLOBAL_Version, + case '0.3' + modified=1; + % in SOFA 0.3, only SimpleFreeFieldHRIR 0.1 was supported. + % Updating SimpleFreeFieldHRIR 0.1 to 0.2 + Obj.GLOBAL_Version='0.4'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + Obj.GLOBAL_TimeCreated=Obj.GLOBAL_DatabaseTimeCreated; + Obj.GLOBAL_TimeModified=Obj.GLOBAL_DatabaseTimeModified; + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.3'); + % remove dimensional variables and not used variables/attributes + dims={'I','R','E','N','M','C','Q','SourceView',... + 'SourceUp','GLOBAL_DatabaseTimeCreated','GLOBAL_DatabaseTimeModified'}; + f=fieldnames(Obj); + for ii=1:length(dims) + for jj=1:length(f) + if strcmp(f{jj},dims{ii}), + Obj=rmfield(Obj,f{jj}); % remove variable or attribute + if isempty(strfind(f{jj},'_')), + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,f{jj}); % remove dimension + end + elseif strcmp(f{jj}(1:min(length(dims{ii})+1,length(f{jj}))),[dims{ii} '_']) + Obj=rmfield(Obj,f{jj}); % remove attributes of that variable + end + end + end + warning('SOFA:upgrade','SOFA 0.3 upgraded to 0.4. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.4' + % in SOFA 0.4, only SimpleFreeFieldHRIR might need upgrade + if strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + switch Obj.GLOBAL_SOFAConventionsVersion + case '0.2' + % Upgrade from SimpleFreeFieldHRIR 0.2 to 0.3 + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SimpleFreeFieldHRIR 0.2'); + % Create temp SourcePosition + azi=bsxfun(@times,Obj.ListenerRotation(:,1),ones(size(Obj.ListenerPosition,1),1)); + ele=bsxfun(@times,Obj.ListenerRotation(:,2),ones(size(Obj.ListenerPosition,1),1)); + r=bsxfun(@times,Obj.ListenerPosition(:,1),ones(size(Obj.ListenerRotation,1),1)); + % Copy ListenerPosition + Obj.ListenerPosition=Obj.SourcePosition; + % Overwrite SourcePosition + Obj.SourcePosition=[azi ele r]; + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degree, degree, meter'; + % Mirror the ListenerView and correct ListenerUp + Obj.ListenerView=-Obj.ListenerView; + Obj.ListenerUp=[0 0 1]; + % Remove irrelevant fields + if isfield(Obj,'SourceView'); Obj=rmfield(Obj,'SourceView'); end + if isfield(Obj,'SourceView_Type'); Obj=rmfield(Obj,'SourceView_Type'); end + if isfield(Obj,'SourceView_Units'); Obj=rmfield(Obj,'SourceView_Units'); end + if isfield(Obj,'SourceUp'); Obj=rmfield(Obj,'SourceUp'); end + if isfield(Obj,'SourceUp_Type'); Obj=rmfield(Obj,'SourceUp_Type'); end + if isfield(Obj,'SourceUp_Units'); Obj=rmfield(Obj,'SourceUp_Units'); end + Obj=rmfield(Obj,'ListenerRotation'); + Obj=rmfield(Obj,'ListenerRotation_Type'); + Obj=rmfield(Obj,'ListenerRotation_Units'); + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,'ListenerRotation'); + Obj.GLOBAL_SOFAConventionsVersion='0.3'; + end + end + modified=1; + Obj.GLOBAL_Version='0.5'; + warning('SOFA:upgrade','SOFA 0.4 upgraded to 0.5. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.5' + % Upgrade from 0.5 to 0.6 + Obj.GLOBAL_DateCreated=Obj.GLOBAL_TimeCreated; + Obj=rmfield(Obj,'GLOBAL_TimeCreated'); + Obj.GLOBAL_DateModified=Obj.GLOBAL_TimeModified; + Obj=rmfield(Obj,'GLOBAL_TimeModified'); + Obj.GLOBAL_Origin=Obj.GLOBAL_Source; + Obj=rmfield(Obj,'GLOBAL_Source'); + if isfield(Obj,'ListenerView') && ~isfield(Obj,'ListenerView_Type') + Obj.ListenerView_Type = 'cartesian'; + Obj.ListenerView_Units = 'meter'; + end + if isfield(Obj,'ReceiverView') && ~isfield(Obj,'ReceiverView_Type') + Obj.ReceiverView_Type = 'cartesian'; + Obj.ReceiverView_Units = 'meter'; + end + if isfield(Obj,'GLOBAL_SubjectID'), + Obj.GLOBAL_ListenerShortName=Obj.GLOBAL_SubjectID; % rename SubjectID to ListenerShortName + Obj=rmfield(Obj,'GLOBAL_SubjectID'); + end + switch Obj.GLOBAL_SOFAConventions + case {'SimpleFreeFieldHRIR', 'SimpleFreeFieldTF'} + Obj.GLOBAL_SOFAConventionsVersion='0.4'; + case {'GeneralFIR', 'GeneralTF', 'SingleRoomDRIR'} + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + end + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.5'); + Obj.GLOBAL_Version='0.6'; + modified=1; + warning('SOFA:upgrade','SOFA 0.5 upgraded to 0.6. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.6' + X=SOFAgetConventions(Obj.GLOBAL_SOFAConventions); + if ~isempty(X), + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.6'); + Obj.GLOBAL_Version='1.0'; + Obj.GLOBAL_SOFAConventionsVersion = X.GLOBAL_SOFAConventionsVersion; + % replace aliases by correct unit names + U=SOFAdefinitions('units'); + Uf=fieldnames(U); + f=fieldnames(Obj); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.(f{jj})=regexprep(Obj.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + f=fieldnames(Obj.Data); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.Data.(f{jj})=regexprep(Obj.Data.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + modified=1; + warning('SOFA:upgrade','SOFA 0.6 upgraded to 1.0. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + else + warning('SOFA:upgrade','Unknown conventions'); + end +end + +%% Upgrade specific to conventions +if ~modified + switch Obj.GLOBAL_SOFAConventions + case 'MultiSpeakerBRIR' + if strcmp(Obj.GLOBAL_SOFAConventionsVersion,'0.1'); + % upgrade to 0.2 + Obj.GLOBAL_DataType='FIRE'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + %Obj.Data.Delay = + if strcmp(Obj.API.Dimensions.Data.Delay,'IR') + Obj.API.Dimensions.Data.Delay='IRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + if strcmp(Obj.API.Dimensions.Data.Delay,'MR') + Obj.API.Dimensions.Data.Delay='MRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + modified=1; + warning('SOFA:upgrade','Conventions MultiSpeakerBRIR 0.1 upgraded to 0.2. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..7191c1c8ea81f39f88a404e427d181d94b084a49 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..cec5aa59ee86045457d0fbd2590b2a0cb6577d32 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..0bb3faa71614827f35429b1a419c7701cc9e2258 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF.csv new file mode 100644 index 0000000000000000000000000000000000000000..85582b97e4315872968a58fccef0054cb3284532 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/FreeFieldDirectivityTF.csv @@ -0,0 +1,59 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions FreeFieldDirectivityTF rm attribute This conventions stores directivities of acoustic sources (instruments, loudspeakers, singers, talkers, etc) in the frequency domain for multiple musical notes in free field. +GLOBAL:SOFAConventionsVersion 0.2 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary, but the spatial setup assumes free field. +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +GLOBAL:InstrumentType m attribute Narrative description of the acoustic source, e.g., 'Violin' or 'Human' +GLOBAL:InstrumentManufacturer m attribute Narrative description of the manufacturer of the source, e.g., 'Stradivari, Lady Blunt, 1721' +GLOBAL:Musician m attribute Narrative description of the musician such as position, behavior, or personal data if not data-protected, e.g., 'Christiane Schmidt sitting on the chair', or 'artificial excitation by R2D2'. +ListenerPosition [0 0 0] m IC, MC double Position of the microphone array during the measurements. +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [0 0 1] m IC, MC double Orientation of the microphone array +ListenerView:Type spherical m attribute +ListenerView:Units degree, degree, metre m attribute +ListenerUp [0 90 1] m IC, MC double Up vector of the microphone array +ListenerUp:Type spherical m attribute +ListenerUp:Units degree, degree, metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double Positions of the microphones during the measurements (relative to the Listener) +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Position of the acoustic source (instrument) +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourcePosition:Reference m attribute Narrative description of the spatial reference of the source position, e.g., for the trumpet, �The bell�. Mandatory in order to provide a reference across different instruments +SourceView [0 0 1] m IC, MC double Orientation of the acoustic source (instrument) +SourceView:Type spherical m attribute +SourceView:Units degree, degree, metre m attribute +SourceView:Reference m attribute Narrative description of the spatial reference of the source view, e.g., for the trumpet, �Viewing direction of the bell�. Mandatory in order to provide a reference across different instruments +SourceUp [0 90 1] m IC, MC double Up vector of the acoustic source (instrument) +SourceUp:Type spherical m attribute +SourceUp:Units degree, degree, metre m attribute +SourceUp:Reference m attribute Narrative description of the spatial reference of the source up, e.g., for the trumpet, �Along the keys, keys up�. Mandatory in order to provide a reference across different instruments +EmitterPosition [0 0 0] m eCI double A more detailed structure of the Source. In a simple settings, a single Emitter is considered that is collocated with the source. +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units degree, degree, metre m attribute +MIDINote I, M double Defines the note played by the source during the measurement. The note is specified a MIDI note by the [https://www.midi.org/specifications-old/item/the-midi-1-0-specification MIDI specifications, version 1.0]. Not mandatory, but recommended for tonal instruments. +Description IS, MS attribute Narrative description of a measurement (recommend for documenting the data), e.g., the note, the musical dynamic (pp., ff., etc.), the string on which the note was played, the playing style (pizzicato, legato, etc.), or the location at which a cymbal was hit. +TuningFrequency I, M double Defines the frequency (in Hertz) the instrument is tuned to during the measurements corresponding to the note A4 (MIDINote = 69). +Data.Real 0 m mRn double The real part of the complex-valued spectrum +Data.Imag 0 m MRN double The imaginary part of the complex-valued spectrum +N 0 m N double Frequencies of the considered spectral bands +N:LongName frequency m attribute +N:Units Hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..cec59b14f4aefe9f8098f06f45bf790aaddb754a Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..5202d2c8c867b67014d7e97a0f840ff5a40bf72a Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..9aec2bd82a3c853930811ab8bbabf3719e488b35 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR.csv new file mode 100644 index 0000000000000000000000000000000000000000..1a77a1a7f46fc715c83a22cc354cedfd304f76de --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIR.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mRn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..7aa2716b52f580a3888fdae0e12878e3289bc71a Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..427ecaefb190389ef6c927945ff3fec68c1f95a0 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..62b8926e10c5c529ce2f11588184fb64f10d96f2 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE.csv new file mode 100644 index 0000000000000000000000000000000000000000..c767c77a815dd871c45098f2e851e17c424cebcf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralFIRE.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIRE rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mREn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..30068b013b794b936fd35e8a6504e4dc9710b9af Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..f9ba97f95cb1ba52a9ac0313dc1ba37936c9735d Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..77fe2933fc83976ff26b5513b1843c30fd773b38 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString.csv new file mode 100644 index 0000000000000000000000000000000000000000..4092d8d9bccc3064f3bc972d65bbdb1206bee68f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralString.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralString rm attribute Conventions for testing the string support +GLOBAL:SOFAConventionsVersion 0.2 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType String rm attribute We store strings here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +String2 {'' ''} m MRS string +String2:Description 2-D string m attribute +String2:Units latin1 m attribute +Data.String1 {''} m MS string +Data.String1:Description 1-D string m attribute +Data.String1:Units latin1 m attribute +Data.String2 {'' ''} m MRS string +Data.String2:Description 2-D string m attribute +Data.String2:Units latin1 m attribute +Data.Double [0 0] m mRn double +Data.Double:Units double m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..abe6aaa39232f579b415b7b7ddb599221d0e1545 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..a8264f7ac2f8c03b2b089e7d624a7d74bbc7bdc2 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..066ccd476f1fb3c55dc05c2abbbda54d6d6c13af Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF.csv new file mode 100644 index 0000000000000000000000000000000000000000..577be53d9365e915ec546b6f15bd9eaf5a566d3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/GeneralTF.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralTF rm attribute This conventions stores TFs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralFIR. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mRn double The real part of the complex spectrum +Data.Imag 0 m MRN double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N_LongName frequency attribute +N_Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..6d7e7e77fa516fc0d18338e9cc2efd7bef338b54 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..1297dd37a0ea159e594ad8f97611b2a9384cb5e1 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..6bcc55e6350943db44182b13ccc95982273ec8ab Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR.csv new file mode 100644 index 0000000000000000000000000000000000000000..bb45db38ab7773c59b5361ca94cdb43d1b8e5122 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/MultiSpeakerBRIR.csv @@ -0,0 +1,48 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions MultiSpeakerBRIR rm attribute This convention is for BRIRs recorded in reverberant conditions from multiple loudspeaker sources at a number of listener orientations. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:RoomDescription attribute narrative description of the room +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +EmitterUp [0 0 1] ECI, ECM double When EmitterUp provided, EmitterView must be provided as well +EmitterView [1 0 0] ECI, ECM double When EmitterView provided, EmitterUp must be provided as well +EmitterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR [1 1] m mREn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IRE, MRE double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..aacba0566e229d10992ed4f327ad897606ec7a41 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..b72f1ec5eee54b7ce04ce88eb11834d826e64a34 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..a906d4fcade3c698c5cbc6c3544bd3e14296371b Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR.csv new file mode 100644 index 0000000000000000000000000000000000000000..cb0a1fef967b431b26d19cd500d37bd87cbc9c47 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldHRIR.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRIR rm attribute This convention set is for HRIRs recorded under free-field conditions or other IRs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..6c1585a9df0db8d111a9a07008db933e465719f1 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..1933196dd3487d0015b14740d7cade1a12e72a9c Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..a69ed596e04bc6681d0b18fdbb2cbd8202ffad83 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS.csv new file mode 100644 index 0000000000000000000000000000000000000000..544332c80789ffbac984b8180307b6e7c66da368 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldSOS.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldSOS rm attribute This convention set follows SimpleFreeFieldHRIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0; 0 0 0 1 0 0], [3 1 2]); m mRn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..30d676ce3a8baa1fc231459e0fb007c7497c50a8 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..a68506e461826ab37baf4f4e1a513d93a3654e70 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..02cd92948f14f0c89e63bdcdd40a5fec07de4e46 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF.csv new file mode 100644 index 0000000000000000000000000000000000000000..bd7da0d66a4904886fe7c33fcd14a321d354256e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleFreeFieldTF.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldTF rm attribute This conventions is for TFs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.Real [0 0] m mRn double +Data.Imag [0 0] m MRN double +N 0 m N double +N_LongName frequency attribute +N_Units hertz attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..026d74c180ba9333e6ec49f862a5dfe7db02aa42 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..a74c0f1274fd65b7f973027f1b23e90b73bb1973 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..56037a9c71ee1b1023bff9b53247033db28deb70 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR.csv new file mode 100644 index 0000000000000000000000000000000000000000..e84cc9382be0cd1a22a74fcd5b2b0224fc7b4f2e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SimpleHeadphoneIR.csv @@ -0,0 +1,51 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SimpleHeadphoneIR rm attribute Conventions for IRs with a 1-to-1 correspondence between emitter and receiver. The main application for this convention is to store headphone IRs recorded for each emitter and each ear. +GLOBAL:SOFAConventionsVersion 0.2 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We will store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute Room type is not relevant here +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Default: Headphones are located at the position of the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0.09 0; 0 -0.09 0] m eCI, eCM double Default: Reflects the correspondence of each emitter to each receiver +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double +GLOBAL:DatabaseName m attribute Correspondence to a database +GLOBAL:ListenerShortName m attribute Correspondence to a subject from the database +GLOBAL:ListenerDescription m attribute Narrative description of the listener (or mannequin) +GLOBAL:SourceDescription m attribute Narrative description of the headphones +GLOBAL:SourceManufacturer m attribute Name of the headphones manufacturer +SourceManufacturer {''} MS string Optional M-dependent version of the attribute SourceManufucturer +GLOBAL:SourceModel m attribute Name of the headphone model. Must uniquely describe the headphones of the manufacturer +SourceModel {''} MS string Optional M-dependent version of the attribute SourceModel +GLOBAL:SourceURI m attribute URI of the headphone specifications +GLOBAL:ReceiverDescription m attribute Narrative description of the microphones +ReceiverDescription {''} MS string Optional M-dependent version of the attribute ReceiverDescription +GLOBAL:EmitterDescription m attribute Narrative description of the headphone drivers +EmitterDescription {''} MS string Optional M-dependent version of the attribute EmitterDescription +MeasurementDate 0 M double Optional M-dependent date and time of the measurement diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-a.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-a.mat new file mode 100644 index 0000000000000000000000000000000000000000..8b3f1b94bbc7893f610557be048d82f966f62ce6 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-a.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-m.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-m.mat new file mode 100644 index 0000000000000000000000000000000000000000..b0ed4fa152c228bd1a0c8356cf396a247883792e Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-m.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-r.mat b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-r.mat new file mode 100644 index 0000000000000000000000000000000000000000..659aadc99065144bf23a95e7007c4be85e866c84 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR-r.mat differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR.csv new file mode 100644 index 0000000000000000000000000000000000000000..89d7443f24ca8bdba685135845b1cd46df1e5ad9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/conventions/SingleRoomDRIR.csv @@ -0,0 +1,45 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SingleRoomDRIR rm attribute This convention stores arbitrary number of receivers while providing an information about the room. The main application is to store DRIRs for a single room. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute +GLOBAL:RoomDescription m attribute +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +SourceUp [0 0 1] m IC, MC double +SourceView [-1 0 0] m IC, MC double +SourceView:Type cartesian m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..97663db3c33bd3a7a7de7057b863705d3ce19196 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertARI2SOFA.m @@ -0,0 +1,46 @@ +function Obj=SOFAconvertARI2SOFA(hM,meta,stimPar) +% OBJ=SOFAconvertARI2SOFA(hM,meta,stimPar) converts the HRTFs described in hM, meta, and +% stimPar (see ARI HRTF format) to a SOFA object. +% + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(hM,1); % hM is [N M R], data.IR must be [M R N] +Obj.Data.SamplingRate = stimPar.SamplingRate; + +%% Fill with attributes +if isfield(stimPar, 'SubjectID'), Obj.GLOBAL_ListenerShortName = stimPar.SubjectID; end +if isfield(stimPar,'Application') + if isfield(stimPar.Application,'Name'), Obj.GLOBAL_ApplicationName = stimPar.Application.Name; end + if isfield(stimPar.Application,'Version'), Obj.GLOBAL_ApplicationVersion = stimPar.Application.Version; end +end + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.2 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) zeros(size(hM,2),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) 1.2*ones(size(hM,2),1)]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with some additional data +Obj.GLOBAL_History='Converted from the ARI format'; +if size(meta.pos,2)>2, Obj=SOFAaddVariable(Obj,'MeasurementSourceAudioChannel','M',meta.pos(1:size(hM,2),3)); end +if isfield(meta,'lat'), Obj=SOFAaddVariable(Obj,'MeasurementAudioLatency','MR',meta.lat); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertBTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertBTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..231df9ccb5b5ec6b9af47bfb5cf0501540bef17d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertBTDEI2SOFA.m @@ -0,0 +1,80 @@ +function Obj = SOFAconvertBTDEI2SOFA(BTDEI) +% OBJ=SOFAconvertBTDEI2SOFA(BTDEI) converts the HRTFs described in BT-DEI +% to a SOFA object. +% +% BTDEI format is used by Michele Geronazzo, University of Padova. +% + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% get empty object (the flag 'm' provides the mandatory fields only) +Obj=SOFAgetConventions('SimpleHeadphoneIR','m'); + +Obj.GLOBAL_Title = 'HPIR'; +Obj.GLOBAL_DatabaseName = BTDEI.specs.Database; + +Obj.GLOBAL_History = 'Converted from the BT-DEI format'; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HpTFs from DEI - University of Padova'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_AuthorContact = 'geronazzo@dei.unipd.it'; +Obj.GLOBAL_References = ['M. Geronazzo, F. Granza, S. Spagnol, F. Avanzini. ', ... + 'A Standardized Repository of Head-Related and Headphone Impulse Response Data ', ... + 'In 134th Convention of the Audio Engineering Society, May 2013.']; +Obj.GLOBAL_Organization = 'Department of Information Engineering, University of Padova'; +Obj.GLOBAL_Comment = ''; + +% copy the data + +% Emitter - Source +Obj.GLOBAL_SourceDescription = [BTDEI.hp.Id ' - ' BTDEI.hp.Producer ' ' BTDEI.hp.Model]; +Obj.GLOBAL_SourceManufacturer = BTDEI.hp.Producer; +Obj.GLOBAL_SourceModel = BTDEI.hp.Model; +%Obj.GLOBAL_SourceURI = BTDEI.hp.Uri; +% Receiver - Listener +Obj.GLOBAL_SubjectID = BTDEI.specs.SubjectId; +Obj.GLOBAL_ListenerDescription = BTDEI.sbjType; +Obj.GLOBAL_ReceiverDescription = BTDEI.specs.MicrophonePosition; % qualitative data e.g. blocked ear canal, open ear canal, at the eardrum + + +Obj.ListenerPosition = [0 0 0]; +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 0]; +Obj.SourcePosition = [0 0 0]; +Obj.EmitterPosition = [0 0.09 0; 0 -0.09 0]; + +%% Fill data with data +Obj.Data.SamplingRate = BTDEI.specs.SampleRate; % Sampling rate + +% calculate the effective size of the data matrix +M = length(BTDEI.data); % number of repositionings +R = size(BTDEI.data(1).HpIR,2); % number of channels (stereo) + +len_vec = zeros(M,1); +for ii=1:M + len_vec(ii)= length(BTDEI.data(ii).HpIR); +end +N = max(len_vec); + +Obj.API.M=M; +Obj.API.R=R; +Obj.API.N=N; + +% store IR data +Obj.Data.IR = NaN(M,R,N); % data.IR must be [M R N] +for aa=1:M + HpIR = [BTDEI.data(aa).HpIR; zeros((N-length(BTDEI.data(aa).HpIR)),2)]; + Obj.Data.IR(aa,1,:)= HpIR(:,1)'; + Obj.Data.IR(aa,2,:)= HpIR(:,2)'; +end + + +% update dimensions +Obj = SOFAupdateDimensions(Obj); +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertCIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertCIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..df1f7b8e8bd70912cc8561099fa831ecf1b982c4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertCIPIC2SOFA.m @@ -0,0 +1,58 @@ +function Obj=SOFAconvertCIPIC2SOFA(CIPIC) +% Obj=SOFAconvertCIPIC2SOFA(CIPIC) converts the HRTFs described in the structure CIPIC +% (see CIPIC HRTF format) to a SOFA object. +% + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +ida=round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1)); +lat=lat1(ida); + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,size(CIPIC.hrir_l,3)); % data.IR must be [M R N] +Obj.Data.SamplingRate = 44100; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=CIPIC.hrir_l(aa,ee,:); + Obj.Data.IR(ii,2,:)=CIPIC.hrir_r(aa,ee,:); + [azi,ele]=hor2sph(lat(ii),pol(ii)); + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = CIPIC.name; +Obj.GLOBAL_History = 'Converted from the CIPIC file format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; +% SimpleFreeFieldHRIR 0.3 and 0.4 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertFHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertFHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..80044c3eadef841e7983a26a9722b748ecba64ca --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertFHK2SOFA.m @@ -0,0 +1,67 @@ +function Obj=SOFAconvertFHK2SOFA(miroObj) +% OBJ=SOFAconvertFHK2SOFA(miroObj) converts the HRTFs described in miroObj +% to SOFA. miroObj is the miro object saved at the Fach-Hochschule Köln +% provided by Benjamin Bernschütz. +% Reference to the source format: http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +% Reference to the source coordinate system: [1] http://code.google.com/p/sofia-toolbox/wiki/COORDINATES + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if isoctave, + error(['Octave is not able to convert FHK to SOFA, use Matlab instead.']); +end + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = miroObj.irChOne; % irChOne is [N M] +Obj.Data.IR(:,:,2) = miroObj.irChTwo; +Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +% Obj.GLOBAL_APIName +% Obj.GLOBAL_ApplicationName +% Obj.GLOBAL_ApplicationVersion +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = miroObj.context; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Fachhochschule Köln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_References = 'Bernschütz, B. (2013). "A Spherical Far Field HRIR/HRTF Compilation of the Neumann KU 100", proceedings of the AIA/DAGA, Meran, Italy'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Origin = 'http://www.audiogroup.web.fh-koeln.de/ku100hrir.html'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='FHK'; +Obj.GLOBAL_Title = 'HRTF'; + +%% Fill the mandatory variables +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + % From [1]: All angles are in RAD. + % AZ denotes the azimutal angle in a range of (0-2pi(. Whereas AZ=0 is defined to be the front direction and AZ=pi to be the rear direction. + % EL denotes the elevation angle in a range of (0-pi). EL=0 points upwards, EL=pi/2 points to the horizontal plane and EL=pi points downwards. + % r is the radius in meters (if needed/specified). +Obj.SourcePosition = [... + rad2deg(miroObj.azimuth') ... % miroObj.azimuth is AZ + 90-rad2deg(miroObj.elevation') ... % miroObj.elevation is EL + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % miro.sourceDistance is r + +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +%Obj.GLOBAL_EmitterDescription =''; +Obj.GLOBAL_RoomDescription = miroObj.location; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertLISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertLISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..cdc267b29fb8d2326bf30182514607ff42d26adf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertLISTEN2SOFA.m @@ -0,0 +1,42 @@ +function Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) +% Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) converts the HRTFs described in LISTEN +% (see LISTEN HRTF format) to a SOFA object. +% + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data + % content_m is [M N], data.IR must be [M R N] +Obj.Data.IR = zeros(size(LISTEN.l_eq_hrir_S.content_m,1),2,size(LISTEN.l_eq_hrir_S.content_m,2)); +Obj.Data.IR(:,2,:)=LISTEN.r_eq_hrir_S.content_m; +Obj.Data.IR(:,1,:)=LISTEN.l_eq_hrir_S.content_m; +Obj.Data.SamplingRate = 48000; % Note: LISTEN.l_eq_hrir_S.sampling_hz contains 44100 which is wrong! + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = subjectID; +Obj.GLOBAL_History='Converted from the LISTEN format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.95 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v zeros(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v 1.95*ones(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertMIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertMIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..db9f6f753aeb1fa5c46030f4c97fb8ffa1eaf654 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertMIT2SOFA.m @@ -0,0 +1,77 @@ +function Obj=SOFAconvertMIT2SOFA(root,pinna) +% OBJ=SOFAconvertMIT2SOFA(root,pinna) loads the MIT HRTFs saved in a +% directory ROOT for the PINNA and converts to a SOFA object. +% PINNA must be 'normal' or 'large'. + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Create correct parts of the file name +% 'L' use full data from left pinna (normal pinna) +% 'R' use full data from right pinna (large red pinna) +% 'H' use compact data -> not supported now +switch pinna + case 'normal' + postfix='L'; idx=[1 2]; + prefix='full'; + case 'large' + postfix='R'; idx=[2 1]; + prefix='full'; + otherwise + error('Pinna not supported'); +end + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90]; +elecnt=[ 56 60 72 72 72 72 72 60 56 45 36 24 12 1]; + +%% Determine data size +M=sum(elecnt); +Obj.SourcePosition=zeros(M,3); +Obj.Data.IR=zeros(M,2,length(audioread([root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav']))); + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + flip_azi = mod(360-azi,360); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(flip_azi)) 'a.wav']; + Obj.Data.IR(ii,idx(1),:) = audioread(fn)'; % data.IR must be [M R N] + dirfn=dir(fn); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(azi)) 'a.wav']; + Obj.Data.IR(ii,idx(2),:) = audioread(fn)'; + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1.4]; + ii=ii+1; + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = ['KEMAR, ' pinna ' pinna']; +Obj.GLOBAL_History='Converted from the MIT format'; +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 +% Obj.ListenerPosition = [1.4 0 0]; +% Obj.ListenerView = [-1 0 0]; +% Obj.ListenerUp = [0 0 1]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..ae730f784c25f2c6f9cc3b54fd63b2a1e63e1bdd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSCUT2SOFA.m @@ -0,0 +1,69 @@ +function Obj=SOFAconvertSCUT2SOFA(root,r) +% OBJ=SOFAconvertSCUT2SOFA(root,pinna) loads the SCUT HRTFs saved in a +% directory ROOT for the radius R and converts to a SOFA object. +% R must be in meters. + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-30 -15 0 15 30 45 60 75 90]; +elecnt=[ 72 72 72 72 72 72 36 24 1]; + +%% Create empty matrix +M=sum(elecnt)*length(r); +Obj.SourcePosition=zeros(M,3); +Obj.Data.IR=zeros(M,2,512); + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for jj=1:length(r) + for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + fn=fullfile(root, ['r' num2str(r(jj)*100)], ['ele' num2str(ele)], ['H' num2str(azi) 'c.pcm']); + dirfn=dir(fn); + fid = fopen(fn, 'r'); + H = fread(fid,'float'); + fclose(fid); + Obj.Data.IR(ii,1,:) = single(H(1:2:1024)); % separate the left-ear HRIR + Obj.Data.IR(ii,2,:) = single(H(2:2:1024)); % separate the right-ear HRIR + Obj.SourcePosition(ii,:) = [mod(360-azi,360) ele r(jj)]; + ii=ii+1; + end + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the SCUT format'; + +Obj.GLOBAL_Author = 'Bosun Xie'; +Obj.GLOBAL_AuthorContact = 'phbsxie@scut.edu.cn'; +Obj.GLOBAL_License = 'CC 3.0 BY-SA-NC'; +Obj.GLOBAL_Organization = 'South China University of Technology, Guangzhou, China'; + +Obj.GLOBAL_References = 'Bosun Xie, 2013, "Head-Related Transfer Function and Virtual Auditory Display", J Ross Publishing Inc., Plantation, FL, USA'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_DatabaseName='SCUT'; + +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + + +%% Fill the mandatory variables +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..90e406c059668271e43fdf71041e29e59b29cf67 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSOFA2ARI.m @@ -0,0 +1,67 @@ +function [hM,meta,stimPar]=SOFAconvertSOFA2ARI(Obj) +% OBJ=SOFAconvertSOFA2ARI(hM,meta,stimPar) converts the HRTFs described in hM, meta, and +% stimPar (see ARI HRTF format) to a SOFA object. +% + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR'), + error('ARI Format supports only SimpleFreeFieldHRIR SOFA conventions'); +end + +%% Fill data matrix +hM=shiftdim(Obj.Data.IR,2); % data.IR is [M R N], hM must be [N M R] + +%% Fill stimPar +stimPar.SamplingRate = Obj.Data.SamplingRate; +stimPar.TimeBase = 1e6/stimPar.SamplingRate; +stimPar.SubjectID = Obj.GLOBAL_ListenerShortName; + +%% Fill meta + % Fill in geodesic coordinate system where azi=(0;360) and ele=(-90;90); +meta.pos(:,1)=bsxfun(@times,Obj.SourcePosition(:,1),ones(Obj.API.M,1)); +meta.pos(:,2)=bsxfun(@times,Obj.SourcePosition(:,2),ones(Obj.API.M,1)); + % Fill in the Channel +if isfield(Obj,'MeasurementSourceAudioChannel'), + meta.pos(:,3) = bsxfun(@times,Obj.MeasurementSourceAudioChannel,ones(Obj.API.M,1)); +else + meta.pos(:,3) = NaN(Obj.API.M,1); +end +if isfield(Obj,'MeasurementAudioLatency'), + meta.lat=bsxfun(@times,Obj.MeasurementAudioLatency,ones(Obj.API.M,1)); +end + % create horizontal-polar coordinates +[meta.pos(:,6), meta.pos(:,7)]=sph2hor(meta.pos(:,1),meta.pos(:,2)); + % create continuous-elevation coordinates where azi=(-90;90) and ele=(0;360); +meta.pos(:,4)=meta.pos(:,1); +meta.pos(:,5)=meta.pos(:,2); +idx=find(meta.pos(:,1)>90 & meta.pos(:,1)<=270); +meta.pos(idx,4)=meta.pos(idx,4)-180; +meta.pos(idx,5)=180-meta.pos(idx,5); +idx=find(meta.pos(:,1)>270 & meta.pos(:,1)<=360); +meta.pos(idx,4)=meta.pos(idx,4)-360; + +%% Fill with unknown but probably mandatory data +% stimPar.Channel = 0; +% stimPar.Electrode = 0; +% stimPar.PulseNr = 0; +% stimPar.Period = 0; +% stimPar.Offset = 0; +stimPar.Resolution = 24; % assume a 24-bit ADC/DAC resolution +% stimPar.FadeIn = 0; +% stimPar.FadeOut = 0; +% stimPar.Length = 0; +% stimPar.FittFileName = ''; +% stimPar.StimFileName = ''; +stimPar.GenMode = 1; +% stimPar.WorkDir = ''; +stimPar.ID = 'hrtf'; +stimPar.Version = '2.0.0'; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSYMARE2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSYMARE2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..f41fb57d749648d1ff8d23de8e4ee3c14576856e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertSYMARE2SOFA.m @@ -0,0 +1,69 @@ +function [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) +% [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) converts objects +% from SYMARE database to Struct in SOFA format. +% +% SYMAREpath of type string specifies the path where the SYMARE directory +% is found +% HRIRname of type string specifies which HRIR out of the +% <SYMAREpath>/HRIRs/Acoustic directory should be converted +% +% Returns Obj in SOFA format which can further be converted into .sofa +% file using SOFAsave + +%% Get an empty conventions structure + +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); +Obj.GLOBAL_Title = 'HRIR'; +Obj.GLOBAL_RoomType = 'free field'; + +%% Fill global attributes +if isempty(strfind(HRIRname,'.mat')) + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-1:end)); +else + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-5:end-4)); +end + +Obj.GLOBAL_AuthorContact ='https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_Comment = ''; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History', ... + 'Converted from the SYMARE database'); +Obj.GLOBAL_License = strcat('Creative Commons Attribution-Non', ... + 'Commercial-ShareAlike 4.0 International Public License'); +Obj.GLOBAL_Organization = 'University of Sydney'; +Obj.GLOBAL_Author = 'Craig Jin, Anthony Tew, et al.'; +Obj.GLOBAL_Origin = 'https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_DateCreated = char(datetime('now','Format','yyyy-MM-dd HH:mm:ss.SSS')); +Obj.GLOBAL_DatabaseName='SYMARE'; + +%% Get SYMARE data and convert to SOFA structure +%m: number of measurements; +%R: number of receivers; +%n: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%HRIR Dimensions : mRn; + +% Get source positions +load(fullfile(SYMAREpath,'HRIRs','Parameters','azim')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','elev')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','r')); +if ~(length(r) == length(azim)) + r(1:size(azim)) = r; + r = r'; +end +Obj.SourcePosition = [azim*180/pi,elev*180/pi,r]; + +% Get sampling frequency +load(fullfile(SYMAREpath,'HRIRs','Parameters','fs')); +Obj.Data.SamplingRate = fs; + +% Get IRs +load(fullfile(SYMAREpath,'HRIRs','Acoustic',HRIRname)); % gets you hR, hL +HRIR(:,:,1) = hL'; % nm -> mnR +HRIR(:,:,2) = hR'; % nm -> mnR +Obj.Data.IR = permute(HRIR,[1 3 2]); % mnR -> mRn + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8f892266fc2c525e3a9b85dcdad7f88383bee954 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTHK2SOFA.m @@ -0,0 +1,138 @@ +function Obj = SOFAconvertTHK2SOFA(miroObj) +% OBJ=SOFAconvertTHK2SOFA(miroObj) converts the HRIRs, BRIRs, and DRIRs +% (VariSphear array measurements) described in miroObj to SOFA. +% miroObj is the miro object saved at the Technische Hochschule Koeln, provided by Benjamin Bernschuetz. +% Reference to the source format: http://www.audiogroup.web.th-koeln.de/FILES/miro_documentation.pdf +% Reference to the source coordinate system: [1] http://www.audiogroup.web.th-koeln.de/SOFiA_wiki/COORDINATES.html +% SOFAconvertTHK2SOFA written by Tim Lübeck, TH Köln, 2018 +% +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% +if isoctave, + error(['Octave is not able to convert THK to SOFA, use Matlab instead.']); +end + +%% Get an empty conventions structure depending on miro format +if ( strcmp (miroObj.type,'HRIR') ) + Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_Title = 'HRIR'; + Obj.GLOBAL_RoomType = 'free field'; + typeFlag = 0; +elseif ( strcmp (miroObj.type,'BRIR') ) + Obj = SOFAgetConventions('MultiSpeakerBRIR'); + Obj.GLOBAL_Title = 'BRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 1; +else %( strcmp (miroObj.type,'MICARRAY') ) + Obj = SOFAgetConventions('SingleRoomDRIR'); + Obj.GLOBAL_Title = 'DRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 2; +end + +%% Fill global attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = [miroObj.context,' / Sampling Grid: ',miroObj.quadGrid]; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Technische Hochschule Koeln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_Origin = 'http://audiogroup.web.th-koeln.de'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='THK'; +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +Obj.GLOBAL_EmitterDescription = miroObj.source; +Obj.GLOBAL_RoomDescription = [miroObj.location,' / avgAirTemp: ',num2str(miroObj.avgAirTemp),' / avgRelHumidity: ',num2str(miroObj.avgRelHumidity)]; + +%% Set miroObj to degree mode +miroObj.shutUp = 1; +miroObj = setDEG(miroObj); + +%% Get miroObject data and convert to SOFA structure +%M: number of measurements; +%R: number of receivers; +%N: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%FIR : [M R N]; + +if (typeFlag == 0 || typeFlag == 1) %BRIR or HRIR + irChOne = zeros(miroObj.returnTaps,miroObj.nIr); + irChTwo = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + IR = getIR( miroObj, channel ); + irChOne(:, channel) = IR(:,1); %[N M] + irChTwo(:, channel) = IR(:,2); %[N M] + end + if (typeFlag == 0) %HRIR + Obj.Data.IR = irChOne; % irChOne is [N M] + Obj.Data.IR(:,:,2) = irChTwo; + Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] + else % BRIR + Obj.Data.IR = zeros(size(irChOne,2), 2, 1, size( irChTwo,1)); %[N 2 1 M] + Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irChOne,-2),3); + Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irChTwo,-2),3); + end +else % DRIR + irData = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + irData(:,channel) = miroObj.getIR(channel); + end + Obj.Data.IR = zeros(1, miroObj.nIr ,miroObj.returnTaps); %[M R N] + for R = 1 : miroObj.nIr + Obj.Data.IR(1,R,:) = irData(:,R); + end + Obj.Data.Delay = zeros(1,miroObj.nIr); +end +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill the mandatory source emitter variables +Obj.ListenerPosition = [0 0 0]; % for BRIR and HRIR listener in center +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; % for HRIR and BRIR ears as receiver + +if (typeFlag == 0)%HRIR + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.SourcePosition = [... + miroObj.azimuth' ... % azimuth angle in a range of (0-360°(. Whereas AZ=0° is defined to be the front direction and AZ=180° to be the rear direction. + 90-miroObj.elevation' ... % elevation angle in range of (0-180°). EL=0 points upwards, EL=90° points to the horizontal plane and EL=180° points downwards. + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % radius in meters +elseif (typeFlag == 1) %BRIR + Obj.SourcePosition = [0 0 0]; % default edit manually! + Obj.EmitterPosition = [miroObj.sourceDistance 0 0]; % default position is center, otherwise define manually + Obj.EmitterPosition_Type = 'cartesian'; + Obj.EmitterUp = [0 0 1]; + Obj.EmitterView = [-1 0 0]; + Obj.ListenerView = [miroObj.azimuth', ... % see HRIR definitions + 90-miroObj.elevation', ... + zeros(size(miroObj.azimuth'))]; %miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ListenerUp = [0 0 1]; +else %DRIR + Obj.SourcePosition = [1,0,0]; % default edit manually! + Obj.EmitterPosition = [0,0,0]; + Obj.ListenerPosition = [0 0 0]; + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ReceiverPosition = [... + miroObj.azimuth' ... + 90-miroObj.elevation' ... + miroObj.radius*ones(size(miroObj.azimuth'))]; + Obj.ReceiverPosition_Type = 'spherical'; + Obj.ReceiverPosition_Units = 'degree, degree, metre'; +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8225d7fcecf0aebfbf99352041761c70f8901025 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTUBerlin2SOFA.m @@ -0,0 +1,56 @@ +function Obj=SOFAconvertTUBerlin2SOFA(irs) +% OBJ=SOFAconvertTUBerlin2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object. +% + +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(shiftdim(irs.left,-1),2); % irs.left is [N M], data.IR must be [M R N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-1),2); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HRTF from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['H. Wierstorf, M. Geier, A. Raake, S. Spors. ', ... + 'A Free Database of Head-Related Impulse Response Measurements in ', ... + 'the Horizontal Plane with Multiple Distances. ', ... + 'In 130th Convention of the Audio Engineering Society, May 2011.']; +Obj.GLOBAL_Origin = 'https://dev.qu.tu-berlin.de/projects/measurements/repository/show/2010-11-kemar-anechoic/mat'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = irs.ears; +Obj.GLOBAL_SourceDescription = irs.source; + +%% Fill the mandatory variables +% SimpleFreeFieldHRIR 0.6 +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.SourcePosition = [nav2sph(rad2deg(irs.apparent_azimuth)') ... + rad2deg(irs.apparent_elevation)' ... + distance.*ones(M,1)]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTUBerlinBRIR2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTUBerlinBRIR2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..02cd289def7a79075843b8e955340ad51684502d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAconvertTUBerlinBRIR2SOFA.m @@ -0,0 +1,72 @@ +function Obj=SOFAconvertTUBerlinBRIR2SOFA(irs) +% OBJ=SOFAconvertTUBerlin2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object, using the MultiSpeakerBRIR +% Convention. +% + +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('MultiSpeakerBRIR'); + +%% Fill data with data +Obj.Data.IR = zeros(size(irs.left,2),2,1,size(irs.left,1)); +Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irs.left,-2),3); % irs.left is [N M], data.IR must be [M R E N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-2),3); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'BRIR from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['']; +Obj.GLOBAL_Origin = 'TU Berlin'; +Obj.GLOBAL_Organization = 'Quality and Usability Lab, Technische Universitaet Berlin'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'BRIR TU Berlin'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = 'Large ears (KB0065 + KB0066) with G.R.A.S. 40AO pressure microphones'; +Obj.GLOBAL_SourceDescription = 'Genelec 8030A'; +Obj.GLOBAL_RoomType = 'reverberant'; +Obj.GLOBAL_RoomDescription = ''; + + +%% Fill the mandatory variables +% MultiSpeakerBRIR +% === Source === +Obj.SourcePosition = [0 0 0]; % center of loudspeaker array +Obj.EmitterPosition = irs.source_position'; +Obj.EmitterView = irs.head_position'; +Obj.EmitterUp = [0 0 1]; +% === Listener === +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.ListenerPosition = irs.head_position'; +[x,y,z] = sph2cart(fixnan(irs.head_azimuth'), ... + repmat(fixnan(irs.head_elevation'),size(irs.head_azimuth')), ... + repmat(distance,size(irs.head_azimuth'))); +Obj.ListenerView = [x,y,z]; +Obj.ListenerUp = [0 0 1]; +% Receiver position for a dummy head (imported from SimpleFreeFieldHRIR) +Obj.ReceiverPosition = [0,0.09,0; 0,-0.09,0]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end + +function x = fixnan(x) + if isnan(x), x=0; end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAhrtf2dtf.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAhrtf2dtf.m new file mode 100644 index 0000000000000000000000000000000000000000..5007c27b3cb147b8cda5766d2673f32481bfaed2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/SOFAhrtf2dtf.m @@ -0,0 +1,164 @@ +function [dtf,ctf]=SOFAhrtf2dtf(hrtf,varargin) +%SOFAHRTF2DTF splits HRTFs into directional transfer functions (DTFs) and +%common transfer functions (CTFs) +% Usage: [dtf,ctf]=SOFAhrtf2dtf(hrtf) +% [dtf,ctf]=SOFAhrtf2dtf(hrtf,f1,f2) +% +% Input parameters: +% hrtf: SOFA object with SimpleFreeFieldHRIR convention +% +% Output arguments: +% dtf: SOFA object with the directional transfer functions +% ctf: SOFA object with the common transfer functions +% +% `SOFAhrtf2dtf(...)` calculates DTFs using the method from either +% Majdak et al. (2010; 'log' flag) or Middlebrooks (1999; 'rms' flag). +% The magnitude spectrum of the CTF is calculated by +% averaging the (log-)magnitude spectra across all HRTFs for each ear. +% The phase spectrum of the CTF is the minimum phase +% corresponding to the magnitude spectrum of the CTF. +% DTFs result from filtering the HRTF with the inverse complex CTF. +% +% `SOFAhrtf2dtf` accepts the following key-value pairs: +% +% 'f1',f1 start frequency of the filtering (in Hz; default: 50 Hz) +% 'f2',f2 end frequency of the filtering (in Hz; default: 18 kHz) +% 'atten',a broadband attenuation in order to avoid clipping (in dB; +% default: 20 dB) +% 'weights' w area weights for averaging. Vector of size [M 1] +% (M=number of HRIRs), or flase (default: false) +% +% `SOFAhrtf2dtf` accepts the following flags: +% +% 'log' evaluate CTF magnitude spectrum by average of log-magnitude +% spectra, equivalent to geometric mean of linear filters +% (c.f., Majdak et al., 2010; Baumgartner et al., 2014). +% This is the default. +% 'rms' evaluate CTF magnitude spectrum by RMS of linear +% magnitude spectra, equivalent to diffuse-field +% compensation (c.f., Middlebrooks, 1999; Moller et al., +% 1995). +% +% References: +% Baumgartner, R., Majdak, P., & Laback, B. (2014). Modeling sound-source +% localization in sagittal planes for human listeners. J. Acoust. Soc. Am. +% 136(2), 791-802. +% Majdak, P., Goupell, M. J., & Laback, B. (2010). 3-D localization of +% virtual sound sources: Effects of visual environment, pointing method, +% and training. Attention, Perception, & Psychophysics, 72(2), 454-469. +% Middlebrooks, J. C. (1999). Individual differences in external-ear +% transfer functions reduced by scaling in frequency. J. Acoust. Soc. Am., +% 106(3), 1480-1492. +% Moller, H., Hammershoi, D., Jensen, C. B., S?rensen, M. F. (1995). +% Design criteria for headphones. J. Audio Eng. Soc., 43(4), 218-232. + + +% Author: Robert Baumgartner, 2014/01/16 +% Fabian Brinkmann, 2016/09/08 - added rms, and weighted averaging +% Piotr Majdak, 2018/02/23 - Octave ifft compatibility + +%% Check Input +definput.keyvals.f1 = 50; % Hz +definput.keyvals.f2 = 18000; % Hz +definput.keyvals.atten = 20; % dB +definput.keyvals.weights = false; +definput.flags.avg = {'log','rms'}; + +[flags,kv]=SOFAarghelper({'f1','f2','atten', 'weights'},definput,varargin); + +%% Settings +kv.fs = hrtf.Data.SamplingRate; +hrtfmtx = shiftdim(hrtf.Data.IR,2); % dim 1: time, dim 2: source position, dim 3: receiver/ear +N = size(hrtfmtx,1); +Nfft = N; %2^nextpow2(N); + +%% Frequency bounds +df = kv.fs/Nfft; +f = 0:df:kv.fs-df; +idx = f >= kv.f1 & f <= kv.f2; +idx(Nfft/2+2:end) = fliplr(idx(2:Nfft/2)); + +%% CTF calculation + +% get magnitude response +hrtff=fft(hrtfmtx,Nfft); +if flags.do_rms + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg=sqrt(sum( abs(hrtff).^2 .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2 )); + else + ctffavg=sqrt(mean(abs(hrtff).^2,2)); + end +else % flags.do_log + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg= sum(log(abs(hrtff)+eps) .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2); + else + ctffavg=mean(log(abs(hrtff)+eps),2); + end +end + +% Force minimum phase +ctfflog=mean(log(abs(hrtff)+eps),2); +ctfcep = ifft(ctfflog,Nfft); +ctfcep(Nfft/2+2:Nfft,:,:) = 0; % flip acausal part to causal part or simply multiply +ctfcep(2:Nfft/2,:,:) = 2*ctfcep(2:Nfft/2,:,:); % causal part by 2 (due to symmetry) +ctfflog = fft(ctfcep,Nfft); +ctfp = exp(ctfflog); + +% get complex spectrum +if flags.do_rms + ctff = ctffavg .*exp(1j*angle(ctfp)); +else + ctff = exp(ctffavg) .*exp(1j*angle(ctfp)); +end + +% get IR +ctfmtx = real(ifft(ctff, Nfft)); + +%% DTF calculation +dtff = hrtff; +dtff(idx,:,:) = hrtff(idx,:,:)./repmat(ctff(idx,:,:),[1 size(hrtff,2) 1]); +dtfmtx = ifft(dtff,Nfft); + +%% Attenuate to avoid clipping +ctfmtx = ctfmtx / 10^(kv.atten/20); +dtfmtx = dtfmtx / 10^(kv.atten/20); + +%% Output Objects +dtf = hrtf; +if size(dtfmtx,3)==1 % handle objects with R=1 + dtfmtx(1,1,2)=0; + dtfmtx = shiftdim(dtfmtx,1); + dtf.Data.IR = dtfmtx(:,1,:); +else + dtf.Data.IR = shiftdim(dtfmtx,1); +end +dtf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Directional transfer functions (DTFs) were generated by removing from the HRTFs the direction-independent log-amplitude spectrum for each ear.']; + +ctf = hrtf; +if size(ctfmtx,2)==1 % handle objects with R=1 + ctf.Data.IR = shiftdim(shiftdata([ctfmtx ctfmtx],3),2); + ctf.Data.IR = ctf.Data.IR(1,:,:); +else + ctf.Data.IR = shiftdim(ctfmtx,1); +end +ctf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Common transfer functions (CTFs) were extracted from the HRTFs in terms of averaging the log-amplitude spectrum for each ear. The phase of a CTF is determined as minimum phase.']; +ctf.SourcePosition = [0 0 0]; + % remove non-standard variables +fc=fieldnames(ctf); +fo=fieldnames(SOFAgetConventions(ctf.GLOBAL_SOFAConventions)); +f=setdiff(fc,fo); % get non-standard fields +f(strncmpi(f,'GLOBAL_',7)) = []; % variables only +ctf=rmfield(ctf,f); % remove +ctf.API.Dimensions=rmfield(ctf.API.Dimensions,f); +ctf = SOFAupdateDimensions(ctf); + + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end; +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/miro.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/miro.m new file mode 100644 index 0000000000000000000000000000000000000000..81e1113389865ad917baf88fbed1dac85f024283 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/converters/miro.m @@ -0,0 +1,1001 @@ +% miro :: Measured Impulse Response Object +% +% miro Class Definition +% +% 2012-2014 Benjamin Bernsch�tz +% 2014-2017 Johannes M. Arend +% 2012-2017 Christoph P�rschmann +% TH K�ln +% University of Applied Sciences +% Institute of Communications Engineering +% Mail christoph.poerschmann@th-koeln.de +% Phone +49 221 8275 2495 +% +% MIRO V1, Release 1.04 - 07/Feb/2014 +% MIRO V1, Release 1.05 - 25/Dez/2016 +% MIRO V1, Release 1.06 - 20/Sep/2017 +% +% Modified Feb/2014 by Chris Pike, BBC R&D +% Modified Dez/2016 by Johannes M. Arend, TH K�ln +% Modified Sep/2017 by Johannes M. Arend & Christoph P�rschmann, TH K�ln + + +classdef miro + + + properties + + name = []; + context = []; + location = []; + date = []; + engineer = []; + contact = []; + comments = []; + miroVersion = []; + type = []; + fs = []; + taps = []; + nIr = []; + excitationSignal = []; + gapTime = []; + microphone = []; + source = []; + audioInterface = []; + micPreamp = []; + capturingSystem = []; + systemLoopLatency = []; + latencyCompensated = []; + headCut = []; + sourcePosition = []; + sourceDistance = []; + avgAirTemp = []; + avgRelHumidity = []; + positionReference = []; + postProcessing = []; + normalization = []; + ctIRnormalization = []; + quadGrid = []; + scatterer = []; + radius = []; + azimuth = []; + elevation = []; + quadWeight = []; + chOne = []; + chTwo = []; + irChOne = []; + irChTwo = []; + centerMicrophone = []; + irCenter = []; + returnTaps = []; + resampleToFS = []; + headWin = []; + tailWin = []; + headPhone = []; + hpcfKernel = []; + headPhoneComp = false; + mic = []; + mcfKernel = []; + micComp = false; + shutUp = false; + angles = 'RAD'; + + end + + methods + + function [ir, azimuth, elevation, quadWeight] = getIR(obj, irID) + + % [ir, azimuth, elevation, quadWeight] = getIR(obj, irID) + % + % Returns the impulse response(s), angles and the + % quadrature weight for a specific ID number [irID]. + % The returned impulse response has two channels + % if the object contains two channels. + % + % irID = 0 adresses the omni center IR. The center IR is + % not filtered by the headphone filter. + + if ~isempty(obj.resampleToFS) + resampleIR = true; + gComDiv = gcd(obj.fs, obj.resampleToFS); + p = obj.resampleToFS / gComDiv; + q = obj.fs / gComDiv; + else + resampleIR = false; + end + + if irID == 0 + + irOne = obj.irCenter(:,1); + irOne = cast(irOne, 'double'); + azimuth = []; + elevation = []; + quadWeight = []; + + else + + irOne = obj.irChOne(:,irID); + irOne = cast(irOne, 'double'); + azimuth = obj.azimuth(irID); + elevation = obj.elevation(irID); + quadWeight = obj.quadWeight(irID); + end + + if obj.headPhoneComp && irID > 0 % Applying HP Filter + if size(obj.hpcfKernel,2)==1 + irOne = miro_fastConv(irOne, obj.hpcfKernel); + else + irOne = miro_fastConv(irOne, obj.hpcfKernel(:,1)); + end + end + + if obj.micComp && irID > 0 % Applying Mic Filter %JMA-Edit + irOne = miro_fastConv(irOne, obj.mcfKernel); + end + + if obj.headWin > 0 % Windowing Head + irOne = miro_winHead(irOne, obj.headWin); + end + + if obj.returnTaps < obj.taps % Truncation + irOne = irOne(1:obj.returnTaps); + end + + if obj.tailWin > 0 % Windowing Tail + irOne = miro_winTail(irOne, obj.tailWin); + end + + ir(:,1) = irOne; + + if ~isempty(obj.irChTwo) && irID > 0 % Channel Two + + irTwo = obj.irChTwo(:,irID); + irTwo = cast(irTwo, 'double'); + + if obj.headPhoneComp + if size(obj.hpcfKernel,2)==1 + irTwo = miro_fastConv(irTwo, obj.hpcfKernel); + else + irTwo = miro_fastConv(irTwo, obj.hpcfKernel(:,2)); + end + end + + if obj.micComp % Applying Mic Filter %JMA-Edit + irTwo = miro_fastConv(irTwo, obj.mcfKernel); + end + + if obj.headWin > 0 % Windowing Head + irTwo = miro_winHead(irTwo, obj.headWin); + end + + if obj.returnTaps < obj.taps % Truncation + irTwo = irTwo(1:obj.returnTaps); + end + + if obj.tailWin > 0 % Windowing Tail + irTwo = miro_winTail(irTwo, obj.tailWin); + end + + ir(:,2) = irTwo; + end + + if resampleIR % Resampling to new FS + ir = resample(ir,double(p),double(q)); + end + + end + + function [irID, azimuth, elevation] = closestIr(obj, az_approx, el_approx) + + % [irID, azimuth, elevation] = closestIr(obj, az_approx, el_approx) + % + % This method returns the ID number [irID] of the closest + % angle to [az_approx, el_approx] that is available + % within the object. [azimuth] and [elevation] return + % the corresponding closest fitting angles + + + if strcmp(obj.angles,'DEG') + az_approx = az_approx*pi/180; + el_approx = el_approx*pi/180; + obj.shutUp = true; + objRAD = setRAD(obj); + quadrature = getQuadrature(objRAD); + else + quadrature = getQuadrature(obj); + end + + [Xg,Yg,Zg] = sph2cart(quadrature(:,1),quadrature(:,2)-pi/2,1); + [Xp,Yp,Zp] = sph2cart(az_approx,el_approx-pi/2,1); + distances = sqrt((Xg-Xp).^2+(Yg-Yp).^2+(Zg-Zp).^2); + irID = find(distances == min(distances)); + azimuth = obj.azimuth(irID); + elevation = obj.elevation(irID); + + end + + function quadrature = getQuadrature(obj) + + % quadrature = getQuadrature(obj) + % + % Returns the quadrature including azimuth and elevation + % angles and weights. + + quadrature(:,1) = double(obj.azimuth); + quadrature(:,2) = double(obj.elevation); + quadrature(:,3) = double(obj.quadWeight); + + end + + function plotQuadrature(obj) + + % plotQuad(obj) + % + % Shows a sphere plot of the quadrature + + obj.shutUp = true; + obj = setRAD(obj); + quadrature = getQuadrature(obj); + + [x,y,z] = sph2cart(quadrature(:,1),quadrature(:,2)-pi/2,1.01); + + colormap Gray; + + if size(x,1)>1500 + plot3(x,y,z,'marker','.','markerfacecolor','g','color','g','linestyle','none') + else + plot3(x,y,z,'marker','o','markerfacecolor','g','color','g','linestyle','none') + end + + axis off; hold on; grid off; sphere; axis equal; rotate3d on; light; + alpha(.6); lighting phong; hold off; set(gcf,'color','w'); + + if strcmp(obj.type,'HRIR') + title(['Sampling Points or Virtural Source Positions in: ',strrep(obj.name,'_','-')]); + elseif strcmp(obj.type,'BRIR') + title(['Head orientations in: ',strrep(obj.name,'_','-')]); %JMA-Edit: Distinguish between HRIR and BRIR type + end + end + + function miroCoordinates(obj) + + % miroCoordinates(obj) + % + % This method illustrates the coordinate system + % that is used by miro + + RAD = true; + + if nargin > 0 + if strcmp(obj.angles,'DEG') + RAD = false; + end + end + + delete(gca) + + line([-5,5],[0,0],[0,0],'Color','r') + hold on + line([0,0],[-5,5],[0,0],'Color','g') + line([0,0],[0,0],[-5,5],'Color','b') + + if RAD + front = 'FRONT: AZ 0/2pi - EL pi/2'; + back = 'BACK: AZ pi - EL pi/2'; + left = 'LEFT: AZ pi/2 - EL pi/2'; + right = 'RIGHT: AZ 3pi/2 - EL pi/2'; + top = 'TOP: AZ x - EL 0'; + bottom = 'BOTTOM: AZ x - EL pi/2'; + else + front = 'FRONT: AZ 0/360� - EL 90�'; + back = 'BACK: AZ 180� - EL 90�'; + left = 'LEFT: AZ 90� - EL 90�'; + right = 'RIGHT: AZ 270� - EL 90�'; + top = 'TOP: AZ x - EL 0�'; + bottom = 'BOTTOM: AZ x - EL 180�'; + end + + text([7,7], [0,0], [0,0], front, 'HorizontalAlignment','center') + text([-7,-7],[0,0], [0,0], back, 'HorizontalAlignment','center') + text([0,0], [7,7], [0,0], left, 'HorizontalAlignment','center') + text([0,0], [-7,-7],[0,0], right, 'HorizontalAlignment','center') + text([0,0], [0,0], [7,7], top, 'HorizontalAlignment','center') + text([0,0], [0,0], [-7,-7],bottom,'HorizontalAlignment','center') + + set(gca,'Projection','perspective'); set(gcf,'color','w'); + box off; axis off; view(-60,34); + title('miro ::: Coordinate System'); + end + + function obj = setDEG(obj) + + % obj = setDEG(obj) + % + % Changes the object's angle reference to DEG. + % All angle handling is then in DEG. + % + % ! The default angle reference is RAD. + + if strcmp(obj.angles,'RAD'); + obj.angles = 'DEG'; + obj.azimuth = obj.azimuth*180/pi; + obj.elevation = obj.elevation*180/pi; + if ~obj.shutUp + fprintf('Angle reference is now DEG.\n'); + end + else + if ~obj.shutUp + fprintf('Angle reference is DEG. (No Change)\n'); + end + end + end + + function obj = setRAD(obj) % Set Angles to RAD + + % obj = setRAD(obj) + % + % Changes the object's angle reference to RAD. + % All angle handling is then in RAD. + % + % ! The default angle reference is RAD. + + if strcmp(obj.angles,'DEG'); + obj.angles = 'RAD'; + obj.azimuth = obj.azimuth*pi/180; + obj.elevation = obj.elevation*pi/180; + if ~obj.shutUp + fprintf('Angle reference is now RAD.\n'); + end + else + if ~obj.shutUp + fprintf('Angle reference is RAD. (No Change)\n'); + end + end + end + + function obj = setReturnTaps(obj, returnTaps, tailWin) + + % obj = setReturnTaps(obj, returnTaps, tailWin) + % + % Allows for changing the number of returned impulse + % response taps. By default, all available taps are + % returned (retunedTaps = taps). Setting the returnedTaps + % property to a smaller value will cause that all returned + % impulse responses are cut off at the value defined by + % [returnTaps] and are by default windowed using a + % half-sided Hann window of the size (returnTaps/8). + % The size of the window can be defined by [tailWin]. + % Using [tailWin = 0] turns off windowing. + + + if returnTaps <= obj.taps + obj.returnTaps = returnTaps; + + if nargin < 3 + obj.tailWin = round(returnTaps/8); + else + obj.tailWin = tailWin; + if tailWin> obj.returnTaps + obj.tailWin = obj.returnTaps; + if ~obj.shutUp + fprintf('Warning: The window cannot be larger than returnTaps!\n') + end + end + end + if ~obj.shutUp + fprintf('returnTaps and tailWin set\n'); + end + else + if ~obj.shutUp + fprintf('ERROR: returnTaps value too large.\n'); + end + end + end + + function obj = setResampling(obj, targetFS) + + % obj = setResampling(obj, targetFS) + % + % Sets the resampleToFS property and can be used to + % extract the IRs at a different audio sampling + % rate. The resampling has effect on the methods: + % getIR(), playAudio() and dropWaveFile(). + % + % targetFS defines the target sampling rate, e.g. 44100Hz + % + % If called without the targteFS argument, the resampleToFS + % property is set to [] (default) and disabled. + % + % The resampling process is done within the getIR method + % after truncation and windowing. The returned IRs then do + % NOT have the amount of samples set in returnTaps property + % as these refer to the original FS. + % + % The resampling is based on the native MATLAB resample() + % method which is included in the Signal Processing Library. + % + % ADVICE: If not urgently necessary try to avoid resampling. + + if nargin < 2 + + obj.resampleToFS = []; + if ~obj.shutUp + fprintf(['Resampling disabled.\n']); + end + + else + obj.resampleToFS = round(targetFS); + if ~obj.shutUp + fprintf(['Resampling enabled and new target FS is set.\n']); + end + end + end + + function dropWaveFile(obj, irID, nBits, filename) + + % dropWaveFile(obj, irID, nBits, filename) + % + % Drops a .WAV audio file containing the impulse + % responses for a specific ID number [irID]. + % The arguments bitdepht [nBits] and filename + % [filename] are optional. + % + % Defaults: + % ------------------------------------------------ + % nBits = 16 + % filename = obj.name,'_IR',num2str(irID), ... + % '-AZ',az, 'EL',num2str(el), ... + % obj.angles, [obj.headphone] + % ------------------------------------------------ + % WARNING: NO DITHERING/NOISESHAPING APPLIED + + if nargin < 3 + nBits = 16; + end + + if nargin < 4 + if strcmp(obj.angles,'RAD') + az = num2str(round(obj.azimuth(irID)*1e4)); + el = num2str(round(obj.elevation(irID)*1e4)); + else + az = num2str(round(obj.azimuth(irID)*1e2)); + el = num2str(round(obj.elevation(irID)*1e2)); + end + filename = [obj.name,'_IR',num2str(irID),'-AZ',az,'EL',num2str(el),obj.angles]; + + if obj.headPhoneComp + filename = [filename,'_',obj.headPhone]; + end + + if obj.micComp + filename = [filename,'_',obj.mic]; %JMA Edit - MCF (needed for NarDasS research project) + end + end + + if strcmp(filename,'NoCoor') %JMA Edit - Small hack to export wav files without any info on coordinates in the filename (needed for NarDasS research project) + filename = ['SSR_',obj.name]; + + if obj.headPhoneComp + filename = [filename,'_',obj.headPhone]; + end + + if obj.micComp + filename = [filename,'_',obj.mic]; %JMA Edit - MCF (needed for NarDasS research project) + end + end + + ir = getIR(obj, irID); + + if isempty(obj.resampleToFS) + %JMA-Edit - Use wavwrite for matlab < 2012b (8.0) and audiowrite for matlab > 2012b + if verLessThan ('matlab','8.0') + wavwrite(ir, obj.fs, nBits, filename); + else + audiowrite([filename,'.wav'], ir, obj.fs, 'BitsPerSample', nBits); + end + else + %JMA-Edit - Use wavwrite for matlab < 2012b (8.0) and audiowrite for matlab > 2012b + if verLessThan ('matlab','8.0') + wavwrite(ir, obj.resampleToFS, nBits, filename); + else + audiowrite([filename,'.wav'], ir, obj.resampleToFS, 'BitsPerSample', nBits); + end + end + if ~obj.shutUp + fprintf(['Wave file has been written.\n']); + end + + end + + function playAudio(obj, irID, audioSignal) + + % playAudio(obj, irID, audioSignal) + % + % Plays an audio signal convolved with the + % impulse response(s) given by irID. + % The method serves for a quick pre-listening + % of the datasets. If the signal [audioSignal] + % has more than one channel, the first channel + % is taken. + + if size(audioSignal,2) > size(audioSignal,1) + audioSignal = audioSignal'; + end + + audioSignal = audioSignal(:,1); + ir = getIR(obj, irID); + + finalAudio(:,1) = miro_fastConv(audioSignal,ir(:,1)); + + if size(ir,2) == 2 + finalAudio(:,2) = miro_fastConv(audioSignal,ir(:,2)); + end + + if ~obj.shutUp + fprintf('Playing audio ...\n'); + end + + if isempty(obj.resampleToFS) + soundsc(finalAudio, obj.fs); + else + soundsc(finalAudio, obj.resampleToFS); + end + + if ~obj.shutUp + fprintf('... done.\n'); + end + + end + + function obj = setHeadPhones(obj, hpcf, linearPhase) + + % obj = setHeadPhones(obj, hpcf, linearPhase) + % + % This method sets headphone compensation filters + % for HRIR and BRIR datasets. The filters are + % applied to all outgoing impulse responses while + % obj.headphoneComp is set "true". + + if strcmp(obj.type,'BRIR') || strcmp(obj.type,'HRIR') + + if nargin < 3 + linearPhase = false; + end + + obj.headPhone = hpcf.hpName; + + if linearPhase + obj.hpcfKernel = hpcf.linPhase; + else + obj.hpcfKernel = hpcf.minPhase; %DEFAULT + end + + obj.headPhoneComp = true; + if ~obj.shutUp + fprintf(['Headphone filters (',hpcf.hpName,') are set.\n']); + end + else + if ~obj.shutUp + fprintf('Headphone filters can only be applied to objects of type HRIR or BRIR.'); + end + return + + end + end + + %JMA Edit - Microphone Compensation Filters (needed for NarDasS research project) + function obj = setMic(obj, mcf, linearPhase) + + % obj = setMic(obj, mcf, linearPhase) + % + % This method sets microphone compensation filters + % for HRIR and BRIR datasets. The filters are + % applied to all outgoing impulse responses while + % obj.micComp is set "true". + + if strcmp(obj.type,'BRIR') || strcmp(obj.type,'HRIR') + + if nargin < 3 + linearPhase = false; + end + + obj.mic = mcf.micName; + + if linearPhase + obj.mcfKernel = mcf.linPhase; + else + obj.mcfKernel = mcf.minPhase; %DEFAULT + end + + obj.micComp = true; + if ~obj.shutUp + fprintf(['Mic compensation filters (',mcf.micName,') are set.\n']); + end + else + if ~obj.shutUp + fprintf('Mic compensation filters can only be applied to objects of type HRIR or BRIR.'); + end + return + + end + end + + function miroToSSR(obj, mirror, nBits, filename, normalize) + + % miroToSSR(obj, mirror, nBits, filename, normalize) + % + % This method writes a 720 channel interleaved + % wave file for the Sound Scape Renderer (SSR): + % + % http://www.tu-berlin.de/?id=ssr + % + % The object must be a circular HRIR or BRIR set. + % + % Defaults: + % ------------------------------------------------ + % mirror = false (not mirrored) + % (This option can be useful for + % symmetrical venues to mirror a source + % e.g. from Left to Right.) + % nBits = 16 + % filename = 'SSR_', obj.name, [obj.headphone] + % normalize= true + % ------------------------------------------------ + % WARNING: NO DITHERING/NOISESHAPING APPLIED + + if (strcmp(obj.type,'BRIR') || strcmp(obj.type,'HRIR')) && obj.nIr == 360 + + if nargin < 2 + mirror = false; + end + + if nargin < 3 + nBits = 16; + end + + if nargin < 4 + if mirror + filename = ['SSR_',obj.name,'_mirror']; + else + filename = ['SSR_',obj.name]; + end + + if obj.headPhoneComp + filename = [filename,'_',obj.headPhone]; + end + + if obj.micComp + filename = [filename,'_',obj.mic]; %JMA Edit - Add mcf + end + + end + + if nargin < 5 + normalize = true; + end + + if mirror + fprintf('Source mirrored '); + end + + irArray = zeros(size(obj.getIR(1),1), 720); + inc = 1; + + for i = 1:360 + if ~mod(i,10) + fprintf('|'); + end + + if mirror + IR = obj.getIR(361-i); + irArray(:,inc) = IR(:,2); + inc = inc+1; + irArray(:,inc) = IR(:,1); + inc = inc+1; + else + IR = obj.getIR(i); + irArray(:,inc) = IR(:,1); + inc = inc+1; + irArray(:,inc) = IR(:,2); + inc = inc+1; + end + end + + fprintf('\n\n'); + + if (normalize) + %disp('Normalizing...'); %JMA-Edit + irArray = 0.99*irArray/max(max(abs(irArray))); + disp('Normalization set true - peak normalization applied'); %JMA-Edit - Always print info about normalization + else + disp('Normalization set false - no peak normalization applied'); + end + + miro_wavwrite([filename,'.wav'], irArray, obj.fs, nBits); %JMA-Edit - Use miro_wavwrite + disp(['SSR file sucessfully generated: ', filename]) + else + if ~obj.shutUp + fprintf('Failed: SSR export requires circular HRIR or BRIR objects.\n'); + end + return + end + end + + function [timeDataCH1, timeDataCH2] = miroToSOFiA(obj) + + % timeData = miroToSOFiA(obj) + % + % Returns structs that are readable by the F/D/T + % function of the SOFiA sound field analysis toolbox. + % The following S/T/C transform core transforms + % the object's data into the spherical harmonics domain. + % + % SOFiA: http://code.google.com/p/sofia-toolbox/ + + obj = obj.setRAD; + + if ~isempty(obj.resampleToFS) + downSampleFactor = obj.fs / obj.resampleToFS; + fs = obj.resampleToFS; + else + downSampleFactor = 1; + fs = obj.fs; + end + + timeDataCH1.FS = double(fs); + timeDataCH1.radius = double(obj.radius); + timeDataCH1.quadratureGrid = obj.getQuadrature; + timeDataCH1.downSample = double(downSampleFactor); + timeDataCH1.averageAirTemp = double(obj.avgAirTemp); + timeDataCH1.irOverlay = 0; + timeDataCH1.centerIR = obj.getIR(0)'; + + timeDataCH1.impulseResponses = zeros(obj.nIr,size(timeDataCH1.centerIR,2)); + + if ~isempty(obj.chTwo) + twoChannels = true; + timeDataCH2.FS = fs; + timeDataCH2.radius = double(obj.radius); + timeDataCH2.quadratureGrid = obj.getQuadrature; + timeDataCH2.downSample = double(downSampleFactor); + timeDataCH2.averageAirTemp = double(obj.avgAirTemp); + timeDataCH2.irOverlay = 0; + timeDataCH2.centerIR = obj.getIR(0)'; + timeDataCH2.impulseResponses = zeros(obj.nIr,size(timeDataCH2.centerIR,2)); + else + twoChannels = false; + timeDataCH2 = []; + end + + for irCnt = 1:obj.nIr + + impulseResponse = obj.getIR(irCnt); + + timeDataCH1.impulseResponses(irCnt,:) = impulseResponse(:,1)'; + timeDataCH1.irOverlay = timeDataCH1.irOverlay + impulseResponse(:,1)'; + + if twoChannels + timeDataCH2.impulseResponses(irCnt,:) = impulseResponse(:,2)'; + end + end + + timeDataCH1.irOverlay=sum(timeDataCH1.impulseResponses,1); + timeDataCH1.irOverlay=abs(timeDataCH1.irOverlay/max(abs(timeDataCH1.irOverlay))); + + if twoChannels + timeDataCH2.irOverlay=sum(timeDataCH2.impulseResponses,1); + timeDataCH2.irOverlay=abs(timeDataCH2.irOverlay/max(abs(timeDataCH2.irOverlay))); + end + end + + end +end + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%Private methods +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +function ab = miro_fastConv(a,b) + +% Internal use only + +NFFT = size(a,1)+size(b,1)-1; +A = fft(a,NFFT); +B = fft(b,NFFT); +AB = A.*B; +ab = ifft(AB); + +end + +function ir = miro_winHead(ir, wLen) + +% Internal use only + +c = 1:wLen; +w = 0.5+0.5*cos(2*pi*(c-((2*wLen-1)/2))/(2*wLen-1)); +ir(1:size(w,2)) = ir(1:size(w,2)) .* w'; + +end + +function ir = miro_winTail(ir, wLen) + +% Internal use only + +c = wLen:2*wLen-1; +w = 0.5+0.5*cos(2*pi*(c-((2*wLen-1)/2))/(2*wLen-1)); +ir(end-size(w,2)+1:end) = ir(end-size(w,2)+1:end) .* w'; + +end + +%CP-Edit: wavwrite function to write multichannel wav files with more than +%512 channels. Required to write wavfiles for the SSR +function [] = miro_wavwrite(filename, Y, Fs, nbits) +%This function writes a multichannel .wav file +%Due to the removement of the wavread function it is currently not possible +%to write or read multichannel wav-files with extremely large number of +%channels (n > 512) +%To create BRIRs or HRIRs for the SSR (SoundScapeRenderer) multi-channel +%.wav-files are required +% Input Parameters: +% filename: Filename of the .wav-File +% Y: Audio data of the .wav-file +% Fs: Sampling rate +% nbits: Number of bits per sample +% C.P�rschmann / TH K�ln / January 2017 + + +if nargin < 4 + nbits=16; +end + +% calculate som relevant values +number_of_channels=length(Y(1,:)); +number_of_samples=length(Y(:,1)); +FileSize=44 + nbits/8 * number_of_channels * number_of_samples; + +%Open File +fileID = fopen(filename,'w'); + +% Write header +fwrite(fileID,'RIFF','*char'); +fwrite(fileID,FileSize-8,'int'); +fwrite(fileID,'WAVE','*char'); +fwrite(fileID,'fmt ','*char'); + +FmtSize=16; +fwrite(fileID,FmtSize,'int'); + +Format=1; +fwrite(fileID,Format,'short'); + +fwrite(fileID,number_of_channels,'short'); + +fwrite(fileID,Fs,'int'); + +BytesPerSecond = Fs*nbits/8*number_of_channels; +fwrite(fileID,BytesPerSecond,'int'); + +Block_Alignment = number_of_channels * nbits/8; +fwrite(fileID,Block_Alignment,'short'); + + +BitsPerSample = nbits ; +fwrite(fileID,BitsPerSample,'short'); + +fwrite(fileID,'data','*char'); + +Datasize = FileSize - 44; +fwrite(fileID,Datasize,'int'); + +% Change Amplitudes from [-1;1] as used in Matlab to integer +Y = Y * (2^(BitsPerSample-1)); + + +for my_loop=1:size(Y,1) + + switch BitsPerSample + case 8 + fwrite(fileID,Y(my_loop,:),'bit8'); + case 16 + fwrite(fileID,Y(my_loop,:),'bit16'); + case 24 + fwrite(fileID,Y(my_loop,:),'bit24'); + case 32 + fwrite(fileID,Y(my_loop,:),'bit32'); + otherwise + error('Error writing SSR_file - Wrong number of bits per sample') + end +end +%Close File +fclose(fileID); + +end + +%CP-Edit: counterpart to miroWavread. Not really needed actually :) +function [Y, Fs, nbits] = miro_wavread(filename) +%This function reads a multichannel .wav file +%Due to the removement of the wavread function it is currently not possible +%to write or read multichannel wav-files with extremely large number of +%channels. +%To create BRIRs or HRIRs for the SSR (SoundScapeRenderer) multi-channel +%.wav-files are required +% Input Parameters: +% filename: Filename of the .wav-File +% Return Values: +% Y: Audio data of the .wav-file +% Fs: Sampling rate +% nbits: Number of bits per sample + +% C.P�rschmann / TH K�ln / January 2017 + + +%open File +fileID = fopen(filename,'r'); + +% read header +my_wave.header.RIFF= fread(fileID,4,'*char'); +my_wave.header.RIFF=my_wave.header.RIFF'; +my_wave.header.RiffSize = fread(fileID,1,'int'); +my_wave.header.WAVE= fread(fileID,4,'*char'); +my_wave.header.WAVE=my_wave.header.WAVE'; +my_wave.header.FMT= fread(fileID,4,'*char'); +my_wave.header.FMT=my_wave.header.FMT'; +my_wave.header.FmtSize = fread(fileID,1,'int'); +my_wave.header.Format = fread(fileID,1,'short'); +my_wave.header.Channels = fread(fileID,1,'short'); +my_wave.header.SamplesPerSecond = fread(fileID,1,'int'); +my_wave.header.BytesPerSecond = fread(fileID,1,'int'); +my_wave.header.BlockAlign = fread(fileID,1,'short'); +my_wave.header.BitsPerSample = fread(fileID,1,'short'); + +%Adjust things, if header is longer than expected +my_wave.header.chunk = fread(fileID,my_wave.header.FmtSize-16,'*char'); + +my_wave.header.nextblock = fread(fileID,4,'*char'); +my_wave.header.nextblock=my_wave.header.nextblock'; + +% IF a 'fact' chunk is included in the wavfile +if my_wave.header.nextblock=='fact' + my_wave.header.fact_length = fread(fileID,1,'int'); + my_wave.header.chunk = fread(fileID,my_wave.header.fact_length,'*char'); + my_wave.header.nextblock = fread(fileID,4,'*char'); + my_wave.header.nextblock=my_wave.header.nextblock'; +end +if my_wave.header.nextblock~='data' + error ('This type of wav-format is not implemented'); +end + +my_wave.header.Datasize = fread(fileID,1,'int'); + +if my_wave.header.Format~=1 + error ('This type of wav-format is not implemented'); +end + + +number_of_samples=my_wave.header.Datasize*8/my_wave.header.BitsPerSample/my_wave.header.Channels; +%read audio data +switch my_wave.header.BitsPerSample + case 8 + Y=fread(fileID,[my_wave.header.Channels number_of_samples],'bit8'); + case 16 + Y=fread(fileID,[my_wave.header.Channels number_of_samples],'bit16'); + case 24 + Y=fread(fileID,[my_wave.header.Channels number_of_samples],'bit24'); + case 32 + Y=fread(fileID,[my_wave.header.Channels number_of_samples],'bit32'); + otherwise + error('Not implemented number of bits per sample in this wav-format') +end +Y=Y'; + +% Change amplitudes from integer to [-1;1] as used in Matlab +Y = Y / (2^(my_wave.header.BitsPerSample-1)); + +%Calculate return values +Fs = my_wave.header.SamplesPerSecond; +nbits = my_wave.header.BitsPerSample; +%Close audio file +fclose(fileID); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/hor2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/hor2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..8b88990afe419687376c694f5129932a9ecdb54e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/hor2sph.m @@ -0,0 +1,38 @@ +function [azi,ele]=hor2sph(lat,pol) +%HOR2SPH transform horizontal-polar to spherical coordinates. +% [azi,ele]=hor2sph(lat,pol) +% +% Input: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also SPH2HOR, SPH2NAV, SPH2VERT, VERT2SPH, NAV2SPH + +% AUTHOR: Robert Baumgartner + +% SOFA API - function hor2sph +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[x,nz,y] = sph2cart(-deg2rad(pol),deg2rad(lat),ones(size(lat))); + +[azi,ele,r] = cart2sph(x,y,-nz); + +azi = rad2deg(azi); +ele = rad2deg(ele); + +% adjust azimuth range +[azi,ele] = nav2sph(azi,ele); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/nav2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/nav2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..bebfd79e4ce39a3c7a1a81212b1b1d77acf57efb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/nav2sph.m @@ -0,0 +1,25 @@ +function [azi,ele]=nav2sph(azi,ele) +%NAV2SPH Coordinate Transform. +% [azi,ele] = nav2sph(azi,ele) vonverts navigational coordinates to +% spherical coordinates. +% +% Input: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also SPH2HOR, SPH2NAV, SPH2VERT, VERT2SPH, HOR2SPH + +% SOFA API - function nav2sph +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +idx=find(azi<0); % azi between -180 and 0 deg +azi(idx) = azi(idx)+360; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/sph2hor.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/sph2hor.m new file mode 100644 index 0000000000000000000000000000000000000000..2dfe7fb23673e35fc98ef17c91ed5ff006b5972a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/sph2hor.m @@ -0,0 +1,41 @@ +function [lat,pol]=sph2hor(azi,ele) +%SPH2HOR transform spherical to horizontal-polar coordinates. +% [lat,pol]=sph2hor(azi,ele) +% +% Input: +% azi ... azimuth (in degrees) +% ele ... elevation (in degrees) +% +% Output: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% See also SPH2NAV, SPH2VERT, VERT2SPH, NAV2SPH, HOR2SPH + +% AUTHOR: Robert Baumgartner + +% SOFA API - function sph2hor +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +[x,y,z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(size(azi))); + +% remove noise below eps +x(abs(x)<eps)=0; +y(abs(y)<eps)=0; +z(abs(z)<eps)=0; + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[pol,nlat,r] = cart2sph(x,z,-y); +pol = rad2deg(pol); +lat = rad2deg(-nlat); + +% adjust polar angle range +pol = mod(pol+90,360)-90; +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/sph2nav.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/sph2nav.m new file mode 100644 index 0000000000000000000000000000000000000000..8d5ad627b379a34424cde8934eb983416506a398 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/coordinates/sph2nav.m @@ -0,0 +1,28 @@ +function [azi,ele] = sph2nav(azi,ele) +%SPH2NAV Coordinate Transform +% [azi,ele] = sph2nav(azi,ele) converts spherical coordinates to +% navigational coordinates. +% +% Input: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% See also SPH2HOR, SPH2VERT, VERT2SPH, NAV2SPH, HOR2SPH + +% SOFA API - function sph2nav +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +azi=mod(azi,360); % wrap to 0 to 360 +idx=find(azi>180 & azi<=360); % azi between 180 and 360 +azi(idx) = -(360-azi(idx)); + +end % end of function \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_ARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_ARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..0b7c16ad45bc3b57cfb0e1e4522f9df1943cf998 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_ARI2SOFA.m @@ -0,0 +1,36 @@ +% SOFA API - demo script +% Load HRTF in ARI format and save as SOFA format + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); +disp(['Loading: ' ARIfn]); +ARI=load(ARIfn); + +%% convert +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); +Obj.GLOBAL_DatabaseName = 'ARI'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test',['ARI_' subjectID '_' ARIfile '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_BTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_BTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..f4c533c8828820306f5601f31111e2bebd0b0fd0 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_BTDEI2SOFA.m @@ -0,0 +1,62 @@ +% SOFA API demo script +% load HRTF in BT-DEI format and save in SOFA format. + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Headphone index of the files to convert +hp= 'H010'; +% Subject index of the files to convert +subject= 'S115'; +% Measurement index of the files to convert +setm= 'Set02'; %Set01 Set02 ... +% File name of the BTDEI file +BTDEIfold='COMPENSATED'; %RAW %COMPENSATED %EQUALIZED +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load BTDEI file \ load database structure data +f=filesep; +BTDEI_hp_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,'headphones_info.mat'); +BTDEI_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,subject,setm,BTDEIfold,'MAT',[hp '_' subject '_btdei.mat']); +disp(['Loading BT-DEI data']); + +try + datasheet = load(BTDEI_hp_add); + BTDEI.hp = datasheet.hp_specs; + + switch subject + case 'S115' + BTDEI.sbjType = 'dummy head with large pinna'; + case 'S116' + BTDEI.sbjType = 'dummy head without pinna'; + case 'S117' + BTDEI.sbjType = 'dummy head without pinna'; + otherwise + BTDEI.sbjType = 'human'; + end + + container = load(BTDEI_add); + BTDEI.specs = container.specs; + BTDEI.data = container.data; +catch e + error(['Convertion - Error message: ' e.message]); +end + +BTDEI.type = BTDEIfold; +BTDEI.typeset = setm; + +%% convert +Obj = SOFAconvertBTDEI2SOFA(BTDEI); +Obj.GLOBAL_Comment = SOFAappendText(Obj,'GLOBAL_Comment',BTDEIfold); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test',['BTDEI-hp_' hp '_subj_' subject '-' setm '-' BTDEIfold '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_CIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_CIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..df130fc4756c219cf345c48790c459955aa541b1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_CIPIC2SOFA.m @@ -0,0 +1,33 @@ +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% load HRTF in CIPIC format and save in SOFA format + +%% Define parameters +% Subject index of the file to convert +subjectID=3; +% File name of the CIPIC file +CIPICfile='hrir_final'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load CIPIC file +CIPICfn=fullfile(fileparts(SOFAdbPath), 'CIPIC', ['subject_' sprintf('%03d',subjectID)], [CIPICfile '.mat']); +disp(['Loading: ' CIPICfn]); +CIPIC=load(CIPICfn); + +%% convert +Obj=SOFAconvertCIPIC2SOFA(CIPIC); +Obj.GLOBAL_DatabaseName = 'CIPIC'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test', ['CIPIC_' 'subject_' sprintf('%03d',subjectID) '_' CIPICfile '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_FHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_FHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..46ca683fd2dc5fe19c19ada335ed193b15b62ab1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_FHK2SOFA.m @@ -0,0 +1,40 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Octave has no support for the miro class of the FHK data +if isoctave, + error(['Octave is not able to convert FHK to SOFA, use Matlab instead.']); +end + +% load HRTF in FHK format and save as SOFA format + +%% Define parameters +% Get a file name of the FHK directory +d=dir(fullfile(fileparts(SOFAdbPath),'FHK','HRIR_*.mat')); +fn=d(1).name; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load FHK file +FHKfn=fullfile(fileparts(SOFAdbPath), 'FHK', fn); +disp(['Loading: ' FHKfn]); +FHK=load(FHKfn); +FHKvar=fieldnames(FHK); +FHKname=FHKvar{1}; +FHKdata=FHK.(FHKname); + +%% convert +Obj=SOFAconvertFHK2SOFA(FHKdata); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofa_api_mo_test', ['FHK_' FHKname '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_HpIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_HpIR.m new file mode 100644 index 0000000000000000000000000000000000000000..f999dfb2831cda414ca1a5d10785cc5c2fcbb634 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_HpIR.m @@ -0,0 +1,34 @@ +% SOFA API - demo script +% load headphone IRs from a SOFA file from the ARI headphones database + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define parameters +% Subject index of the file to convert +subjectID='NH5'; + +%% Load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'headphones', 'ari', ['hpir_' lower(subjectID) '.sofa']); +disp(['Loading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot amplitude spectra +figure; +hold on; box on; +cols=['bgrmky']; +meastime=[0; diff(X.MeasurementDate)]; +for ii=1:X.API.M + plot(20*log10(abs(fft(squeeze(X.Data.IR(ii,1,:)),X.Data.SamplingRate))),cols(ii)); + if ii>1, leg{ii}=['#' num2str(ii) ':' num2str(meastime(ii)) ' seconds later']; end +end +axis([0 X.Data.SamplingRate/2 -80 20]); +leg{1}='#1, first measurement'; +legend(leg); + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_LISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_LISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..a12e8c1c80855f5a4ecd5dbe9acbf129d8329afa --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_LISTEN2SOFA.m @@ -0,0 +1,34 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% load HRTF in LISTEN format and save as SOFA format + +%% Define parameters +% Subject index of the file to convert +subjectID='1002' +% File name of the LISTEN file +LISTENfile=['IRC_' subjectID '_C_HRIR']; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load LISTEN file +LISTENfn=fullfile(fileparts(SOFAdbPath),'LISTEN',['IRC_' subjectID],'COMPENSATED','MAT','HRIR',[LISTENfile '.mat']); +disp(['Loading: ' LISTENfn]); +LISTEN=load(LISTENfn); + +%% convert +Obj=SOFAconvertLISTEN2SOFA(LISTEN,subjectID); +Obj.GLOBAL_DatabaseName = 'LISTEN'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test',['LISTEN_' subjectID '_' LISTENfile '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_MIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_MIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..dfec8d2fb47fb33d16883a26187f1ba1cadf9c6d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_MIT2SOFA.m @@ -0,0 +1,32 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% load HRTF in MIT format and save as SOFA format + +%% Define parameters +% Two ears are available: normal and large. Select one. +pinna='normal'; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +MITfn=fullfile(fileparts(SOFAdbPath),'MIT KEMAR'); +disp(['Loading: ' MITfn ', pinna:' pinna]); + +%% load and convert +Obj=SOFAconvertMIT2SOFA(MITfn,pinna); +Obj.GLOBAL_DatabaseName = 'MIT'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofa_api_mo_test', ['MIT_KEMAR_' pinna '_pinna.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..47e2acee2be48542268bffb93a806d17f4b2b650 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SCUT2SOFA.m @@ -0,0 +1,37 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% load HRTF in MIT format and save as SOFA format + +%% Define parameters +% Two ears are available: normal and large. Select one. +pinna='normal'; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +SCUTdata = 'nearfield'; +SCUTroot=fullfile(fileparts(SOFAdbPath),'SCUT',SCUTdata); +disp(['Loading: ' SCUTroot]); + +%% Define radii for converting +radius=[0.2 0.25 0.3:0.1:1]; +% radius=0.2; + +%% load and convert +Obj=SOFAconvertSCUT2SOFA(SCUTroot,radius); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +str=sprintf('%g,',radius); +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test',['SCUT_KEMAR_radius_' str(1:end-1) '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..311e71e13011439e4c7274acdc1f8b099e8d9d75 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFA2ARI.m @@ -0,0 +1,38 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% load HRTF in SOFA format and save as ARI format + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); +disp(['Loading: ' ARIfn]); +ARI=load(ARIfn); + +%% convert from ARI to SOFA +disp('Converting to SOFA...'); +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); + +%% convert back from SOFA to ARI +disp('Converting back to ARI (hM, meta, stimPar)...'); +[hM, meta, stimPar]=SOFAconvertSOFA2ARI(Obj); + +%% Calculate the differences +disp(['RMS difference between the new hM and the original ARI.hM: ' num2str(sum(sum(sqrt(mean((hM-ARI.hM).^2)))))]); +if sum(sum(sqrt(mean((hM-ARI.hM).^2))))>1, error('hM and ARI.hM not identic'); end +disp(['RMS difference between the new meta.pos and the original ARI.meta.pos: ' num2str(sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2))))]); +if sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2)))>1, error('meta.pos and ARI.meta.pos not identic'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAHRTF2DTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAHRTF2DTF.m new file mode 100644 index 0000000000000000000000000000000000000000..1f3b63fa77eed99ae1d9ef8e364af0a9e4a20472 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAHRTF2DTF.m @@ -0,0 +1,59 @@ +% SOFA API - demo script +% Copyright (C) 2012-2014 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. +% +% load HRTF and plots CTF and average DTF +% + +%% Define parameters +% Subject index of the file to convert +subject=3; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'database', 'cipic', ['subject_' sprintf('%03d',subject) '.sofa']); +X=SOFAload(SOFAfn); +[D,C]=SOFAhrtf2dtf(X); + +% close all; +f = figure; +set(f, 'Position', [50, 400, 1100, 500]); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,1,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(C.Data.IR(1,1,1:length(C.Data.IR)/2)))))); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,2,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +[D,CC]=SOFAhrtf2dtf(D); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('left'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best') + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,1:length(C.Data.IR)/2))))),'r'); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,2,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('right'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAexpandcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAexpandcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..43982e7a3bb3e85ab783035749b560c0d9143584 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAexpandcompact.m @@ -0,0 +1,52 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% This demo shows how to use SOFAexpand and SOFAcompact +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Expanding the objects +x=whos('Obj'); +disp('Expanding the objects'); +tic; +clear Expanded +for ii=1:length(radius) + Expanded(ii)=SOFAexpand(Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Expanded'); +disp([' Expanded object array is now larger by ' num2str(round((y.bytes-x.bytes)/1024)) ' kb']); + +%% Compress the object +disp('Compressing the objects'); +tic; +clear Compacted +for ii=1:length(radius) + Compacted(ii)=SOFAcompact(Expanded(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Compacted'); +disp([' Compacted object array is now as small as the original one. Difference: ' num2str(round((x.bytes-y.bytes)/1024)) ' kb']); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..d93b0bf25f11a8434943d88b0c35ad98f576c141 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAload.m @@ -0,0 +1,74 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Path definitions +SOFAfile=fullfile(SOFAdbPath, 'database', 'tu-berlin', 'qu_kemar_anechoic_all.sofa'); + +%% Loading the full object +disp(['Loading full object: ' SOFAfile]); +tic; +ObjFull=SOFAload(SOFAfile); +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% Loading metadata +disp('Loading all metadata and partial data only'); +tic; +Meta=SOFAload(SOFAfile,'nodata'); + +%% Get index of measurements with the same directions +azi=0; ele=0; +idx=find(Meta.SourcePosition(:,1)==azi & Meta.SourcePosition(:,2)==ele); + +%% Load the parts of the full objects +disp('Loading partial data only'); +clear Obj +for ii=1:length(idx); + Obj(ii)=SOFAload(SOFAfile,[idx(ii) 1]); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('Obj'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Load parts of multiple dimensions of the full object +%e.g. only left ear for source positions 0�-90� at distance 1m +tic +idxSTART=find(Meta.SourcePosition(:,1)==0 & Meta.SourcePosition(:,3)==1); +idxEND=find(Meta.SourcePosition(:,1)==90 & Meta.SourcePosition(:,3)==1); +idxCOUNT=idxEND-idxSTART+1; +disp('Loading partial data in multiple dimensions') +ObjPartMultDim=SOFAload(SOFAfile,[idxSTART idxCOUNT],'M',[1 1],'R'); +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('ObjPartMultDim'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Extract and plot the fully loaded data +IRsFull=squeeze(ObjFull.Data.IR(idx,1,:)); +legFull=num2str(ObjFull.SourcePosition(idx,3)); +subplot(1,2,1); +plot(IRsFull'); +legend(legFull); +title(['Demo of SOFAload:' 10 ... + 'Fully loaded data']); +xlabel(['Index (Sample Taps), fully loaded']); +ylabel('Amplitude'); + +%% Extract and plot the partially loaded data +IRs=zeros(length(idx), Obj(1).API.N); +for ii=1:length(idx) + IRs(ii,:)=squeeze(Obj(ii).Data.IR(:,1,:)); + leg{ii}=num2str(Obj(ii).SourcePosition(:,3)); +end +subplot(1,2,2); +plot(IRs'); +legend(leg); +title(['IRs for the left ear with radius as parameter' 10 ... + 'Partially loaded data']); +xlabel(['Index (Sample Taps), partially loaded']); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..39be170ebe3844e979a899d7f9c2f74b39343657 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAmerge.m @@ -0,0 +1,57 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% This demo shows how to use SOFAmerge +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects to be merged +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Merging the objects +disp('Merging to a single SOFA object'); +tic; +ObjFull=Obj(1); +for ii=2:length(radius) + ObjFull=SOFAmerge(ObjFull,Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% save the object as a single SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test',[TUBfile 'radius_' sprintf('%g_',radius) 'm.sofa']); +disp(['Saving: ' SOFAfn]); +tic; +Obj=SOFAsave(SOFAfn, ObjFull, compression); +x=whos('ObjFull'); +disp(['Saved ' num2str(round(x.bytes/1024)) ' kb in ' num2str(toc) ' s.']); + +%% Plot IRs for a single direction but different radius +azi=0; ele=0; +idx=find(Obj.SourcePosition(:,1)==azi & Obj.SourcePosition(:,2)==ele); +plot(squeeze(ObjFull.Data.IR(idx,1,:))'); +legend(num2str(ObjFull.SourcePosition(idx,3))) +title(['Demo of SOFAmerge:' 10 ... + 'IRs for the left ear with radius as parameter retrieved from a merged object']); +xlabel(' index (sample taps)'); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..f0303a58ed6cae7ab6e402607f72e29683c2a2f8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAplotHRTF.m @@ -0,0 +1,25 @@ +% demo_SOFAplotHRTF - script demonstrating the usage of SOFAplotHRTF +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file in SimpleFreeFieldHRIR +SOFAfile=fullfile(SOFAdbPath,'database','ari','dtf_nh2.sofa'); +Obj=SOFAload(SOFAfile); + +% plot ETC horizontal plane +figure; +SOFAplotHRTF(Obj,'ETCHorizontal',1); +% plot magnitude spectrum in the median plane, channel 2 +figure; +SOFAplotHRTF(Obj,'MagMedian',2); + +%% load a GeneralTF SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari (sim)','hrtf_nh5_ref.sofa'); +Obj=SOFAload(SOFAfile); +% plot magnitude spectrum in the median plane, channel 1 +figure; +SOFAplotHRTF(Obj,'MagMedian',1); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..cf33d2fa3dc19f81dafadb79f7081168a3b5234b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAsave.m @@ -0,0 +1,69 @@ +%% +% This demo creates an artificial HRTF set. +% It shows how to use SOFAgetConventions and SOFAsave +% The HRTF set contains single pulses placed at sample index of 100 +% which results in a broadband delay of 100 samples. +% Each IR is 256 samples long (i.e., N=256) + +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Set parameters +% Latency of the created IRs +latency=100; % in samples, must be 1<latency<256 +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +%% Create the impulse response +N=256; +IR=[zeros(latency,1); 1; zeros(N-latency-1,1)]; + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History = 'created with a script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test','Pulse.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..24f8d7a72046081e615e748ce7c880c45c4315ac --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAspat.m @@ -0,0 +1,52 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define the filename of the SOFA HRTFs +database='ari'; HRTFfilename='hrtf_nh4.sofa'; +% database='cipic'; HRTFfilename='subject_003.sofa'; +% database='listen'; HRTFfilename='irc_1002.sofa'; +% database='mit'; HRTFfilename='mit_kemar_normal_pinna.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_0.5m.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_all.sofa'; + +%% Define the trajectory +azi=[-45 90 0]; % azimuth angles in degrees. If negative values are found, navigational system (-180;+180) will be used. +ele=[0 0 -30 90]; %elevation angles in degrees + +%% Load the HRTFs +fullfn=fullfile(SOFAdbPath, 'database', database, HRTFfilename); +disp(['Loading ' fullfn]); +Obj=SOFAload(fullfn); + +%% Create an input signal +in=randn(5*Obj.Data.SamplingRate,1); % Five seconds of noise + +%% Spatialize +[out,azi,ele,idx]=SOFAspat(in,Obj,azi,ele); +disp('Binaural signal rendered'); + +%% Plot the trajectories +time = (1:length(azi))/Obj.Data.SamplingRate; + +figure +subplot(2,1,1); +plot(time,azi); % plot azimuthal trajectory +ylabel('Azimuth (deg)'); +title('SOFAspat: Trajectory'); + +subplot(2,1,2); +plot(time,ele); % plot elevational trajectory +ylabel('Elevation (deg)'); +xlabel('Time (s)'); + +%% Play the sound - use headphones! +if ~exist('dontplay','var'); + p=audioplayer(out, Obj.Data.SamplingRate); + play(p); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAstrings.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAstrings.m new file mode 100644 index 0000000000000000000000000000000000000000..3cabf7d541715707f9f104193f59176e5103103f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAstrings.m @@ -0,0 +1,68 @@ +% Script for testing the string array feature of SOFA + + +%% Test Strings as application-specific variable +% Load some arbritrary HRTFs +hrtf = SOFAload(fullfile(SOFAdbPath, 'database','ari','dtf_nh2.sofa')); +% Add a string array +str={}; +for ii=1:hrtf.API.M + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +% SOFAaddVariable(Obj,Name,Dim,Value) +hrtf2 = SOFAaddVariable(hrtf,'Test','MS',str); +% Save as SOFA +SOFAsave('stringtest_applicationvar.sofa',hrtf2); +% Reload the file +hrtf = SOFAload('stringtest_applicationvar.sofa'); +% compare the strings +if prod(strcmp(hrtf.Test,hrtf2.Test)) + disp('SimpleFreeFieldHRIR: String Load-Reload: OK'); + delete('stringtest_applicationvar.sofa'); +else + error('String comparison showed differences'); +end +clear all + + +%% Test with conventions GeneralString +% Create an empty object +Obj = SOFAgetConventions('GeneralString'); +% Create numeric data with M=15, R=2, N=10 +Obj.Data.Double=rand(15,2,10); +% Create string arrays +str2={}; str={}; +for ii=1:15 + id = num2str(round(rand(1,1)*1000000)); + str{ii,1}=['X' id]; + str2{ii,1}=['Left' id]; + str2{ii,2}=['Right' id]; +end +Obj.String2 = str2; % String1=[MRS] +Obj.Data.String1 = str; % Data.String1=[MS] +Obj.Data.String2 = str2; % Data.String2=[MRS] +% Add a new string with dimensions [RS] +strn={'left ear'; 'right ear'}; +Obj = SOFAaddVariable(Obj, 'Ears', 'RS', strn); +% Update dimensions +Obj = SOFAupdateDimensions(Obj); +% Save as SOFA +SOFAsave('stringtest_generalstring.sofa',Obj); +% Reload the file +Obj2 = SOFAload('stringtest_generalstring.sofa'); +% Compare the strings +if ~prod(strcmp(Obj2.Data.String2,Obj.Data.String2)) + error('Data.String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.String2,Obj.String2)) + error('String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.Data.String1,Obj.Data.String1)) + error('Data.String1: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.Ears,Obj.Ears)) + error('Ears: Comparison showed differences'); +end +disp('GeneralString: String1, String2, Data, Ears: Load-Reload: OK'); +clear all +delete('stringtest_generalstring.sofa'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAvariables.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAvariables.m new file mode 100644 index 0000000000000000000000000000000000000000..523f2ac978482533ad98145d5ebc632721d6e3ea --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SOFAvariables.m @@ -0,0 +1,58 @@ +% SOFA API - script demonstrating the usage of variables in the API +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari','hrtf_nh5.sofa'); +Obj=SOFAload(SOFAfile); + +%% read an API internal variable +M=Obj.API.M; % read M, the number of measurements +disp(['The number of measurements, M, is ' num2str(M)]); + +%% add a user-defined variable and check it + % create a random variable with the size M +myvar=rand(M,1); + % add to Obj +Obj=SOFAaddVariable(Obj,'MyVariable','M',myvar); + % check if it's there and identical to the created one +if ~all((Obj.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the size is M +if ~all(size(Obj.MyVariable)==[M 1]), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% add a private variable + % create a random variable with the size 1000 x 10 +privatevar=rand(1000,10); + % add to Obj as private +Obj=SOFAaddVariable(Obj,'MyVariable','Private',privatevar); + % check if it's there and identical to the created one +if ~all((Obj.PRIVATE.MyVariable-privatevar)<=eps('single')), error('Error!'); end + % check if the size is 1000 x 10 +if ~all(size(Obj.PRIVATE.MyVariable)==[1000 10]), error('Error!'); end + +%% Save the object + % create a random file name +fn=[mfilename '_temp_' num2str(rand(1,1)) '.sofa']; +SOFAsave(fn,Obj); + +%% Reload the object and remove the temporary file +Obj2=SOFAload(fn); +delete(fn); + +%% Check if the user-defined variable is still there +if ~isfield(Obj2,'MyVariable'), error('Error!'); end + % check if the size is M +if ~all(size(Obj2.MyVariable)==[M 1]), error('Error!'); end + % check if it is identical to the created one +if ~all((Obj2.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj2.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% Make sure that the private variable is not there! +if isfield(Obj2,'PRIVATE'), error('Error!'); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SimpleFreeFieldHRIR2TF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SimpleFreeFieldHRIR2TF.m new file mode 100644 index 0000000000000000000000000000000000000000..e42ae37e2b81447e0f6788196d6b43ec3288ff54 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SimpleFreeFieldHRIR2TF.m @@ -0,0 +1,56 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Convert data from SingleFreeFieldHRIR to SingleFreeFieldTF, extract a few +% frequency bins and save. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% HRTF or DTF? +ARIfile='hrtf'; +% Which frequency bins to store? +bins=[10, 20, 50, 70]; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load file in SimpleFreeFieldHRIR Conventions +f=filesep; +SOFAfn=fullfile(SOFAdbPath,'database','ari', [ARIfile '_' lower(subjectID) '.sofa']); +disp(['Loading: ' SOFAfn]); +IR=SOFAload(SOFAfn); + +%% Get a new SimpleFreeFieldTF conventions +TF=SOFAgetConventions('SimpleFreeFieldTF'); +disp('Converting SimpleFreeFieldHRIR to SimpleFreeFieldTF'); + +%% Copy variables and metadata +TFempty=rmfield(TF,fieldnames(SOFAgetConventions('SimpleFreeFieldTF','r'))); % skip all read-only metadata +Xf=fieldnames(rmfield(TFempty,{'API','Data'})); % skip other internal +for ii=1:length(Xf) + if isfield(IR, (Xf{ii})), TF.(Xf{ii})=IR.(Xf{ii}); end % copy if available +end + +%% Transform data +TF.Data.Real=zeros(IR.API.M,IR.API.R,length(bins)); +TF.Data.Imag=zeros(IR.API.M,IR.API.R,length(bins)); +TF.N=(bins*IR.Data.SamplingRate/IR.API.N)'; + +for ii=1:IR.API.M + cplx=fft((IR.Data.IR(ii,:,:))); + TF.Data.Real(ii,:,:)=real(cplx(:,:,bins)); + TF.Data.Imag(ii,:,:)=imag(cplx(:,:,bins)); +end + +%% Update dimensions +Obj=SOFAupdateDimensions(TF); + +%% Save +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test',['ARI_' ARIfile '_' subjectID '_' num2str(length(bins)) '_freqs.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn,Obj,compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SingleRoomDRIROldenburg.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SingleRoomDRIROldenburg.m new file mode 100644 index 0000000000000000000000000000000000000000..c4825c9b370e993f55915d7c94ecaae4e64d5d31 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_SingleRoomDRIROldenburg.m @@ -0,0 +1,135 @@ +% demo for SingleRoomDRIR: save DRIR data from Uni Oldenburg (Office II) as +% SOFA file and plot the speaker and listener positions. +% It uses conventions SingleRoomDRIR and RoomType 'shoebox', defined by +% RoomCornerA and RoomCornerB. + +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Based on the bachelor thesis of Wolfgang Hrauda (2013). + +% Measurement situation: +% T_60 = 300 ms +% speaker positions: +% entrance, desk, desk, at window (A, B, C, D) +% conditions: +% for position A and D: door and window were open +% Listener: headorientation = {1 2} -> 0�/-90� (straight/looking over right shoulder) +% Receivers: +% ch 1 & 2: 'in-ear' IRs from in-ear microphoes (not available for Office I) +% 'bte' 6-channel BTE-IRs: +% ch 3 & 4: 'front' BTE-IRs front microphone pair +% ch 5 & 6: 'middle' BTE-IRs middle microphone pair +% ch 7 & 8: 'rear' BTE-IRs rear microphone pair +% ambient noise: telepohne, keyboard typing, ventilation (all for both +% orientations); opening and closing the door (15 times) + + +%% Define parameters + + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% --- loading Uni Oldenburg data ---- +PathO=fullfile(fileparts(SOFAdbPath), 'Oldenburg','HRIR_database_mat','hrir','office_II'); +disp(['Loading: ' PathO]); +A1 = load([PathO filesep 'office_II_1_A.mat']); % has dimension: N x R +B1 = load([PathO filesep 'office_II_1_B.mat']); +C1 = load([PathO filesep 'office_II_1_C.mat']); +D1 = load([PathO filesep 'office_II_1_D.mat']); +A2 = load([PathO filesep 'office_II_2_A.mat']); +B2 = load([PathO filesep 'office_II_2_B.mat']); +C2 = load([PathO filesep 'office_II_2_C.mat']); +D2 = load([PathO filesep 'office_II_2_D.mat']); + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SingleRoomDRIR'); + +%% Listener and Receiver +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 9; ... % in-ear + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % front bte + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % middle bte + 0.02 0.09 0.02; 0.02 -0.09 0.02]; % rear bte +Obj.ListenerPosition = [2.16 4.4 1.1]; +Obj.ListenerUp = [0 0 1]; +Obj.ListenerView = [repmat([1 0 0],4,1); repmat([0 -1 0],4,1)]; + +%% Source and Transmitter + +Obj.EmitterPosition = [0 0 0]; +A = [0.52 5.27 1.8]; +B = [0.79 1.25 1.1]; +C = [2.52 1.23 1.1]; +D = [2.38 0 1.8]; +Obj.SourcePosition = [A; B; C; D; A; B; C; D;]; +Av = [-1 0 0]; +Bv = [1 0 0]; +Cv = [1 0 0]; +Dv = [1 0 0]; +Obj.SourceView = [Av; Bv; Cv; Dv; Av; Bv; Cv; Dv;]; +Obj.SourceUp = [0 0 1]; + +%% Fill Data with data +% change data matrix dimension: N x R -> M x R x N +A1.data = shiftdim(A1.data,1); +data(1,:,:) = A1.data; +B1.data = shiftdim(B1.data,1); +data(2,:,:) = B1.data; +C1.data = shiftdim(C1.data,1); +data(3,:,:) = C1.data; +D1.data = shiftdim(D1.data,1); +data(4,:,:) = D1.data; +A2.data = shiftdim(A2.data,1); +data(5,:,:) = A2.data; +B2.data = shiftdim(B2.data,1); +data(6,:,:) = B2.data; +C2.data = shiftdim(C2.data,1); +data(7,:,:) = C2.data; +D2.data = shiftdim(D2.data,1); +data(8,:,:) = D1.data; +Obj.Data.IR = data; +Obj.Data.Delay = zeros(1,size(Obj.Data.IR,2)); +Obj.Data.SamplingRate = A1.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'HATS'; +Obj.GLOBAL_History='Converted from the Uni Oldenburg database'; +Obj.GLOBAL_License='http://medi.uni-oldenburg.de/hrir/html/download.html'; +Obj.GLOBAL_References='H. Kayser, S. D. Ewert, J. Anem�ller, T. Rohdenburg, V. Hohmann, and B. Kollmeier, "Database of Multichannel In-Ear and Behind-the-Ear Head-Related and Binaural Room Impulse Responses," EURASIP Journal on Advances in Signal Processing, vol. 2009, doi:10.1155/2009/298605'; + +%% Setup the room +Obj.GLOBAL_RoomType='shoebox'; +Obj.GLOBAL_RoomDescription='Office II at the University of Oldenburg, T_60 = 300 ms'; + +Obj.RoomCornerA = [0; 0; 0]; +Obj.RoomCornerA_Type = 'cartesian'; +Obj.RoomCornerA_Units = 'meter'; +Obj.API.Dimensions.RoomCornerA='C'; + +Obj.RoomCornerB = [3.3; 6; 0]; +Obj.RoomCornerB_Type = 'cartesian'; +Obj.RoomCornerB_Units = 'meter'; +Obj.API.Dimensions.RoomCornerB='C'; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofa_api_mo_test','Oldenburg_OfficeII.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); +clear Obj; + +%% Re-load the file +disp(['Reloading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot the 2D-plan of the measurement setup +SOFAplotGeometry(X); +title('Office II from Kayser et al. (2009) saved as SingleRoomDRIR'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_TUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_TUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..4507b8feee771691c1e5951bafa1ccc878b0932d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/demos/demo_TUBerlin2SOFA.m @@ -0,0 +1,38 @@ +% SOFA API - demo script +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% load HRTF in TU Berlin format and save as SOFA format + +%% Define parameters +% Prefix to the files +TUBfile = 'QU_KEMAR_anechoic_'; +% Define vector with radii to be loaded. Available files: 0.5, 1, 2, and 3 m +% radius=[0.5 1 2 3]; +radius=[0.5]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load, convert, and save the requested TU-Berlin files +for ii=1:length(radius) + % load + TUBfn=fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR', [TUBfile num2str(radius(ii)) 'm.mat']); + disp(['Loading: ' TUBfn]); + TUB=load(TUBfn); + % convert and add application specific metadata + Obj=SOFAconvertTUBerlin2SOFA(TUB.irs); + Obj.GLOBAL_DatabaseName = 'TU-Berlin'; % maybe setting the name by function parameter + Obj.GLOBAL_ApplicationName = 'Demo of the SOFA API'; + Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + Obj.GLOBAL_Organization = 'Technische Universit�t Berlin'; + Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; + % save + SOFAfn=fullfile(SOFAdbPath, 'sofa_api_mo_test', ['TU-Berlin_' TUBfile 'radius_' sprintf('%g',radius(ii)) 'm.sofa']); + disp(['Saving: ' SOFAfn]); + Obj=SOFAsave(SOFAfn, Obj, compression); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/deg2rad.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/deg2rad.m new file mode 100644 index 0000000000000000000000000000000000000000..45eb15fc654fa4ae6b4b38d521fe616d27245268 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/deg2rad.m @@ -0,0 +1,26 @@ +function phi = deg2rad(phi) +%DEG2RAD returns the given angle in radians +% phi = deg2rad(phi) converts the angle phi given in degree to radians +% +% Input options: +% phi - angle, can be a scalar or matrix (degree) +% +% Output options: +% phi - angle (rad) +% +% See also: RAD2DEG + +% SOFA API - function deg2rad +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Checking of input parameters +narginchk(1,1); + +% Convert angle +phi = phi./180*pi; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargchar.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargchar.m new file mode 100644 index 0000000000000000000000000000000000000000..08ceba0554affa8e9e41d4386f13d356b725461c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargchar.m @@ -0,0 +1,52 @@ +function isargchar(varargin) +%ISARGCHAR tests if the given arg is a char and returns an error otherwise +% +% Usage: isargstruct(arg1,arg2,...) +% +% Input options: +% args - list of args +% +% ISARGCHAR(args) tests if all given args are a char and returns +% an error otherwise. +% +% see also: isargstruct + +%***************************************************************************** +% Copyright (c) 2010-2012 Quality & Usability Lab * +% Deutsche Telekom Laboratories, TU Berlin * +% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% * +% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% * +% The SFS is free software: you can redistribute it and/or modify it under * +% the terms of the GNU General Public License as published by the Free * +% Software Foundation, either version 3 of the License, or (at your option) * +% any later version. * +% * +% The SFS is distributed in the hope that it will be useful, but WITHOUT ANY * +% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * +% FOR A PARTICULAR PURPOSE. * +% See the GNU General Public License for more details. * +% * +% You should have received a copy of the GNU General Public License along * +% with this program. If not, see <http://www.gnu.org/licenses/>. * +% * +% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * +% field synthesis methods like wave field synthesis or higher order * +% ambisonics. * +% * +% http://dev.qu.tu-berlin.de/projects/sfs-toolbox sfstoolbox@gmail.com * +%***************************************************************************** + +% AUTHOR: Hagen Wierstorf +% $LastChangedDate: 2012-04-26 10:12:51 +0200 (Thu, 26 Apr 2012) $ +% $LastChangedRevision: 710 $ +% $LastChangedBy: wierstorf.hagen $ + + +%% ===== Checking for struct ============================================= +for ii = 1:nargin + if ~ischar(varargin{ii}) + error('%s need to be a string.',inputname(ii)); + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargfile.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargfile.m new file mode 100644 index 0000000000000000000000000000000000000000..4394ae470f887a0b722a2c198f97526d0db64962 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargfile.m @@ -0,0 +1,52 @@ +function isargfile(varargin) +%ISARGFILE tests if the given arg is a file and returns an error otherwise +% +% Usage: isargfile(arg1,arg2,...) +% +% Input options: +% args - list of args +% +% ISARGFILE(args) tests if all given args are a file and returns +% an error otherwise. +% +% see also: isargdir + +%***************************************************************************** +% Copyright (c) 2010-2012 Quality & Usability Lab * +% Deutsche Telekom Laboratories, TU Berlin * +% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% * +% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% * +% The SFS is free software: you can redistribute it and/or modify it under * +% the terms of the GNU General Public License as published by the Free * +% Software Foundation, either version 3 of the License, or (at your option) * +% any later version. * +% * +% The SFS is distributed in the hope that it will be useful, but WITHOUT ANY * +% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * +% FOR A PARTICULAR PURPOSE. * +% See the GNU General Public License for more details. * +% * +% You should have received a copy of the GNU General Public License along * +% with this program. If not, see <http://www.gnu.org/licenses/>. * +% * +% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * +% field synthesis methods like wave field synthesis or higher order * +% ambisonics. * +% * +% http://dev.qu.tu-berlin.de/projects/sfs-toolbox sfstoolbox@gmail.com * +%***************************************************************************** + +% AUTHOR: Hagen Wierstorf +% $LastChangedDate: 2012-04-26 10:12:51 +0200 (Thu, 26 Apr 2012) $ +% $LastChangedRevision: 710 $ +% $LastChangedBy: wierstorf.hagen $ + + +%% ===== Checking for file ============================================= +for ii = 1:nargin + if ~ischar(varargin{ii}) || ~exist(varargin{ii},'file') + error('%s need to be a file.',inputname(ii)); + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargstruct.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargstruct.m new file mode 100644 index 0000000000000000000000000000000000000000..53df6ce16a96f7f3fd453d7e38c4cc7521024f1c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isargstruct.m @@ -0,0 +1,52 @@ +function isargstruct(varargin) +%ISARGSTRUCT tests if the given arg is a struct and returns an error otherwise +% +% Usage: isargstruct(arg1,arg2,...) +% +% Input options: +% args - list of args +% +% ISARGSTRUCT(args) tests if all given args are a struct and returns +% an error otherwise. +% +% see also: isargchar + +%***************************************************************************** +% Copyright (c) 2010-2012 Quality & Usability Lab * +% Deutsche Telekom Laboratories, TU Berlin * +% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% * +% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% * +% The SFS is free software: you can redistribute it and/or modify it under * +% the terms of the GNU General Public License as published by the Free * +% Software Foundation, either version 3 of the License, or (at your option) * +% any later version. * +% * +% The SFS is distributed in the hope that it will be useful, but WITHOUT ANY * +% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * +% FOR A PARTICULAR PURPOSE. * +% See the GNU General Public License for more details. * +% * +% You should have received a copy of the GNU General Public License along * +% with this program. If not, see <http://www.gnu.org/licenses/>. * +% * +% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * +% field synthesis methods like wave field synthesis or higher order * +% ambisonics. * +% * +% http://dev.qu.tu-berlin.de/projects/sfs-toolbox sfstoolbox@gmail.com * +%***************************************************************************** + +% AUTHOR: Hagen Wierstorf +% $LastChangedDate: 2012-04-26 10:12:51 +0200 (Thu, 26 Apr 2012) $ +% $LastChangedRevision: 710 $ +% $LastChangedBy: wierstorf.hagen $ + + +%% ===== Checking for struct ============================================= +for ii = 1:nargin + if ~isstruct(varargin{ii}) + error('%s need to be a struct.',inputname(ii)); + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isoctave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isoctave.m new file mode 100644 index 0000000000000000000000000000000000000000..a2ae8884862c9083100e59dc30bc33ec0675e6ea --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/isoctave.m @@ -0,0 +1,43 @@ +function bool = isoctave() +%ISOCTAVE True if the operating environment is octave. +% +% Usage: t = isoctave(); +% +% ISOCTAVE returns 1 if the operating environment is Octave, otherwise +% 0 (Matlab) + +%***************************************************************************** +% Copyright (c) 2010-2012 Quality & Usability Lab * +% Deutsche Telekom Laboratories, TU Berlin * +% Ernst-Reuter-Platz 7, 10587 Berlin, Germany * +% * +% This file is part of the Sound Field Synthesis-Toolbox (SFS). * +% * +% The SFS is free software: you can redistribute it and/or modify it under * +% the terms of the GNU General Public License as published by the Free * +% Software Foundation, either version 3 of the License, or (at your option) * +% any later version. * +% * +% The SFS is distributed in the hope that it will be useful, but WITHOUT ANY * +% WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * +% FOR A PARTICULAR PURPOSE. * +% See the GNU General Public License for more details. * +% * +% You should have received a copy of the GNU General Public License along * +% with this program. If not, see <http://www.gnu.org/licenses/>. * +% * +% The SFS is a toolbox for Matlab/Octave to simulate and investigate sound * +% field synthesis methods like wave field synthesis or higher order * +% ambisonics. * +% * +% http://dev.qu.tu-berlin.de/projects/sfs-toolbox sfstoolbox@gmail.com * +%***************************************************************************** + +% AUTHOR: Hagen Wierstorf +% $LastChangedDate: $ +% $LastChangedRevision: $ +% $LastChangedBy: $ + + +%% ===== Main ============================================================ +bool = ( exist('OCTAVE_VERSION','builtin') ~= 0 ); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/rad2deg.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/rad2deg.m new file mode 100644 index 0000000000000000000000000000000000000000..e75f02bccfc48da40b732a20e35e8b119c7adaba --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/helper/rad2deg.m @@ -0,0 +1,26 @@ +function phi = rad2deg(phi) +%RAD2DEG returns the given angle in degree +% phi = rad2deg(phi) converts the angle phi given in radians to degree +% +% Input options: +% phi - angle, can be a scalar or matrix (rad) +% +% Output options: +% phi - angle (degree) +% +% See also: deg2rad + +% SOFA API - function rad2deg +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% Checking of input parameters +narginchk(1,1); + +% Convert angle +phi = phi./pi*180; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/history.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/history.txt new file mode 100644 index 0000000000000000000000000000000000000000..70e268bbcec0c489e18addef94e217ce00a61194 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/history.txt @@ -0,0 +1,270 @@ +************************************************************* +*** History of SOFA API for Matlab and Octave +*** Acoustics Research Institute, Austrian Academy of Sciences, Vienna +*** Project leader: Piotr Majdak, piotr@majdak.com +*** Contributors: +*** Michael Mihocic +*** Harald Ziegelwanger +*** Hagen Wierstorf +*** Wolfgang Hrauda +*** Fabian Brinkmann +*** Felix Perchfler +************************************************************* + +*** DEVELOPMENT STATUS *** + +*** v1.1.3 +- bug fixes from unreleased SOFA API v1.1.2 merged to latest version of branch v1: +- SOFAplotGeometry: bug fix if no SourceView given +- FreeFieldDirectivityTF: missing eCM in EmitterPosition fixed +- SOFAcheckFilename: do not convert if filename is http:// +- SOFAplotHRTF: plot TF with regular frequency grid. Not tested for irregular grids, though... + + +*** v1.1.2 +- v1.1.2 is the first version of SOFA branch v1; major updates are implemented in master branch (v2) +- SOFAconvertConventions: bug fixed when converting from SimpleFreeFieldTF/GeneralTF or from SimpleFreeFieldSOS + to SimpleFreeFieldHRIR: N has not been removed from the API.Dimensions structure + +*** v1.1.1 +- SOFAstart: bug fix when starting for the first time +- SOFAconvertTUBerlinBRIR2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertTHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertFHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAappendText.m: example added to help +- SOFAcompileConventions: fix for changes in Octave 4.2 +- FreeFieldDirectivityTF: updated to version 0.2 + +*** v1.1.0 (not released) +- SOFAremoveVariable added. It removes a variable from the SOFA object. +- SOFAplotGeometry: show SourceView, and bug fix ListenerView. +- SOFAdbPath, SOFAdbURL: reset the path/URL to the default if the parameter is 'reset'. +- SOFAhrtf2dtf: handling for R=1 added. +- SOFAfind added: Find an index for a given position (draft, to be improved). +- SOFAload: provide error message on loading unknown conventions + +*** v1.0.4 (29.4.2019) +- on "SOFA upgrade warning", display a message on how to switch it off +- SOFAplotHRTF: 'magsagittal' added to plot HRTFs along a sagittal plane. +- SOFAload can use filenames beginning with "db://" to indicate to load from the database (local or remote) +- SOFAstart avoids repeated starts now - + - once SOFAstart has been started, SOFAstart won't be executed fully again, when the paths are still available. + - Call SOFAstart('restart') if a restart needs to be forced. + + +*** v1.0.3 (5.9.2018) +- automatic load of the netcdf package in Octave on SOFAstart +- SOFAspat: bugs in normalization, actual position selection removed +- SOFAhrtf2dtf: RMS and weighted averaging added, Octave compatibility ensured +- SOFAcompileConventions: bug fix when compiling conventions in Octave 4.2.1 +- test_SOFAall: suppress irrelevant warnings +- SOFAconvertMIT2SOFA: wavread replaced by audioread +- SOFAconvertConventions: it can convert from SimpleFreeFieldTF to SimpleFreeFieldHRIR. +- SOFAplotHRTF: more variable input of parameters, normalization optional +- SOFAconvertTHK2SOFA: converter from THK format (in miro format) to SOFA added. + +*** v1.0.2 (16.8.2016) +- SOFAplotHRTF: extended to SimpleFreeFieldTF and some cases of GeneralTF +- SOFAplotGeometry: extended to SimpleFreeFieldTF +- SOFAconvertTUBerling2SOFA: uses MultiSpeakerBRIR now +- SOFAspat, SOFAcalculateAPV: minor bug fixes + +*** v1.0.1 (10.6.2015) +- miro class is not supported in Octave. Error is thrown in demo_FHK2SOFA and converterFHK2SOFA +- demo_BTDEI2SOFA: bug fix in renamed BTDEI files +- demo_SOFA2ARI: bug fix in coordinate comparison + +*** v1.0.0 (3.6.2015) +- 'short' flag added to SOFAstart in order to show only a short header on start-up. +- warnings are function-specific now and can be specifically enabled/disabled. + +*** v0.9.1 (13.5.2015) +- 0.9.1 is the internal numbering for the release version 1.0 RC2 +- SimpleFreeFieldSOS added +- SOFAexpand and SOFAaddVariable handle Data. variables now +- SOFAplotHRTF supports SimpleFreeFielsSOS now + +*** v0.9.0 (12.5.2015) + +- 0.9.0 is the internal numbering for the release version 1.0 RC1 +- update of all conventions to SOFA 1.0 +- changes according to the AES212-standard implemented +- Octave: upgraded to a new netcdf-package: http://modb.oce.ulg.ac.be/mediawiki/index.php/Octave-netcdf +- Matlab/Octave: NETCDF* functions merged for both systems (thx to Hagen Wierstorf) +- HRTFs directory: database handling improved: + - SOFAdbPath mirrors http://sofacoustics.org/data now. + - Warning: directory structure of HRTFs/SOFA changed! + - all SOFA files created by demo_ will be saved in sofa_api_mo_test + - all demo_ files which use SOFA files will be automatically downloaded from sofacoustics.org +- clean up of comments +- SOFAcalculateAPV: reimplemented +- horsph and sph2hor: bug fixes +- directory CDL deleted (had historical relevance only) +- SOFAdefinitions: flag 'units' added for unit aliases. +- SOFAgetConventions: returns empty vector if conventions not supported + +*** v0.4.4 (until 20.4.2015) unreleased + +*** v0.4.3 (5.6.2014) by Piotr Majdak +- fix: annoying bug in SOFAupgradeConventions + +*** v0.4.2 (7.4.2014) by Piotr Majdak +- fix: SOFAhrtf2dtf supports more than two receivers + +*** v0.4.1 (30.3.2014) by Piotr Majdak +- MultiSpeakerBRIR conventions added +- SOFAcompact: compacts variables along dimensions, opposite to SOFAexpand. Functionality not complete for 3D variables +- SOFAcompare: compares two SOFA objects. Preliminary functionality; compares attributes only +- SOFAexpand: expanding of Data added +- bug fix: SOFAplotGeometry +- function-specific warnings added: SOFA:upgrade and SOFA:save +- SOFAload optimized for handling huge (3.7 GB) data files on a 4 GB RAM machine + + +*** v0.4 (19.3.2014) by Piotr Majdak +- implements SOFA 0.6: + - GLOBAL_Source renamed to GLOBAL_Origin + - GLOBAL_TimeCreated and GLOBAL_TimeModified renamed to GLOBAL_DateCreated and GLOBAL_DateModified, respectively + - If ListenerUp is provided, ListenerView must be provided as well. If ListenerView is provided, ListenerView_Type and ListenerView_Units must be provided as well. This also applies to Source, Emitter, and Receiver objects. + - Geometry: only "cartesian" or "spherical" coordinate systems allowed + - In SimpleFreeFieldHRIR: GLOBAL_SubjectID renamed to GLOBAL_ListenerShortName +- Converters adapted to provide more precise information +- SOFAappendText added for appending a text to an attribute +- SOFAdefinitions: returns various definitions, depending on the input flag +- SOFAupgradeConventions: upgrades conventions up to 0.6 now. + +*** v0.3.1 (2.9.2013) by Piotr Majdak +- zip file required 7-zip, fixed +- minor bug fixes + +*** v0.3.0 (27.8.2013) by Piotr Majdak +- major change: .API added to the structure, contains .Dimensions and the dimension sizes (formely known as .DimSize) +- implements SOFA 0.5 (without the support for string arrays) +- upgrade of SimpleFreeFieldHRIR 0.3 and other conventions +- syntax of convention files .csv adapted to that from the specs ("_" replaced by ":") +- SOFAcalculateAPV added, provides calculation of the apparent position vector (APV) +- SOFAplotGeometry added, rudimentary plotting available for SimpleFreeFieldHRIR and SingleRoomDRIR +- SOFAaddVariables supports private variables now + +*** v0.2.9 (30.5.2013) by Piotr Majdak +- development snapshot for the draft of SOFA 0.4 +- tested for Matlab (Octave support not finished yet) +- conventions implemented as CSV files which are compiled to MAT at start and are cached by SOFAgetConventions +- user-defined HRTF database path +- seemless download of remote SOFA files on SOFAload +- user-defined HRTF internet repository +- seemless upgrade from SOFA 0.3 files on SOFAload + +*** v0.2.1 (13.5.2013) by Piotr Majdak +- Bug fix with the wrong spelling of "License" +- "License" it very restrictive per default now +- demo_SOFAsave included + +*** v0.2.0 (2.5.2013) by Piotr Majdak +- Updated to SOFA 0.3 +- Octave support added +- demo_* create file names compliant with MS DOS FAT character set +- test script (test/test_SOFAall.m) added +- converters do not add database specific attriubutes, this is done in demo_* +- new demos: SOFAmerge, SOFAload, SOFAsave +- readme improved +- Pulse.sofa removed as binary, it can be created with demo_SOFAsave now +- Link to HRTF files saved as SOFA added (nice for playing around) + +*** v0.1.4 (2.5.2013) by Piotr Majdak +- Major bug fix: dimension order reversed while loading/saving in Matlab +- Some other minor issues closed +- Ready for intercompatibility test between Matlab and Octave + +*** v0.1.3 (18.4.2013) by Piotr Majdak +- This version implements SOFA specs version 0.2 with the following limitations: + - no Octave support + - only SimpleFreeFieldHRIR supported and tested + +- Detailed changes: + - directory structure changed + - new converter added: SOFA2ARI + - SOFAdbPath added + +*** v0.1.2 (17.4.2013) by Piotr Majdak +- SOFAload: partial loading added. Load of metadata only or by measurement section +- docs: changes since AES2013-specs added. +- history file moved to docs +- Repository cleaned from older stuff + +*** v0.1.1 (16.4.2013) by Piotr Majdak +- SOFAload improved: checks added. Still further checks would be nice, but it can be used now. +- SOFAsave improved: saves user-defined variables +- SOFAexpand added: expands the singleton dimensions in the SOFA object +- Convertors for MIT KEMAR, LISTEN, and CIPIC databases added (with corresponding demos) +- HRTF directory created where all HRTFs should be stored. The convertors rely on that. +- SOFAspat improved, now the engine works better + +*** v0.1.0 (11.4.2013) by Piotr Majdak +- Saving/Loading works in Matlab, it is quite rudimentary now: + - Data and Variables saved as Double + - No string in variables supported yet + - One Conventions implemented and tested (SingleFreeFieldHRIR) + - Loading: no checks (todo) + - Saving: removes optional variables (bug) + - No partial loading/saving yet +- Convertion: ARI2SOFA with demo_ARI2SOFA added +- Spatialization: very rudimentary demo added (SOFAspat and demo_SOFAspat), just for fun + +*** v0.0.12 (12.3.2013) by Piotr Majdak +- Conventions: transmitter renamed to emitter + +*** v0.0.11 (7.3.2013) by Piotr Majdak +- Conventions added +- Octave branch deleted +- Examples: ARI2SOFA as a function +- General: adapted to current specs. Don't use yet. + +*** v0.0.10 (5.3.2013) by Piotr Majdak +- ARI2SOFA: changed to a function now, the fields are more clear defined +- SOFAsave: transmitted and receiver separated, dimensions changed +- Specs have drastically changed - beware of using this version at the current development state + +*** v0.0.9 (31.1.2013) by Piotr Majdak +- included octave part from Hagen Wierstorf +- changed the data structure format +- added try-catch to SOFAsave to avoid open file handles + +*** v0.0.8 (24.08.2012) by Wolfgang Hrauda +- changed data structure format +- updates and fixes in several functions and scripts +- added Eigenmike.sofa as a demo file + +*** v0.0.7 (23.08.2012) by Wolfgang Hrauda +- now using structures or cells as input and output values of functions +- added and renamed several functions and scripts +- updates in several functions and scripts + +*** v0.0.6 (14.08.2012) by Wolfgang Hrauda +- added new functions for coordinate type conversion +- functionality of SOFAgetData slightly expanded +- dismissed function SOFAloadVariables (is now an option in SOFAload) +- "ARI_to_SOFA_lab_setup" updated +- minor fixes in several functions + +*** v0.0.5 (08.08.2012) by Wolfgang Hrauda +- implemented additional dimensions for string variables in SOFAsave +- added new function SOFAloadVariables (a variant of SOFAload) +- added new demo script "ARI_to_SOFA_lab_setup" +- fixes in several functions + +*** v0.0.4 (07.08.2012) by Wolfgang Hrauda +- fixed some issues in SOFAsave +- minor changes in SOFAload +- added new functions SOFAgetID, SOFAgetData, SOFAlistVariables + +*** v0.0.3 (03.08.2012) by Wolfgang Hrauda +- split demo script in two API functions and one script that calls them +- change file extension to 'sofa' + +*** v0.0.2 (01.08.2012) by Wolfgang Hrauda +- finished matrix dimension check + +*** v0.0.1 (31.07.2012) by Wolfgang Hrauda +- demo script that loads ARI .mat file, converts it to SOFA format and writes to .nc-file + then reads all data from .nc.file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFdisplay.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFdisplay.m new file mode 100644 index 0000000000000000000000000000000000000000..7da2fccb5de946906e358c1d2b00a6123a116b38 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFdisplay.m @@ -0,0 +1,15 @@ +function [] = NETCDFdisplay(filename) +%NETCDFDISPLAY +% [] = NETCDFdisplay(filename) displays information about specified SOFA file + +% SOFA API - function netcdf/NETCDFdisplay +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +ncdisp(filename); + +end %of function diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFload.m new file mode 100644 index 0000000000000000000000000000000000000000..26bef0e391527286f9c2f0be4b70ad5282a210a8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFload.m @@ -0,0 +1,154 @@ +function [Obj,Dims] = NETCDFload(filename,flags,varargin) +%% NETCDFLOAD +% Obj = NETCDFload(filename,'all') reads the SOFA object OBJ with all data from +% a SOFA file. +% +% Obj = NETCDFload(filename,'nodata') ignores the Data. variables while +% reading. +% +% Obj = NETCDFload(filename,[START COUNT],partialDim) reads only COUNT number of data +% in dimension partialDim (given as string) beginning with the index START. If START +% and COUNT are column vectors, then partialDim has to be a string containing the +% dimension for every column entry. +% +% [Obj,Dims] = NETCDFload(...) returns the dimension variables found in +% the file as a string. + +% 10.8.2014: string array support. Works for 1D and 2D strings only. +% +% SOFA API - function netcdf/NETCDFload +% Copyright (C) 2012 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob = 'GLOBAL_'; +globid = netcdf.getConstant('GLOBAL'); + +%% --------------------------- N E T C D F load -------------------------- +% Open the NETCDF file +try + var = 'opening file'; + ncid = netcdf.open(filename,'NC_NOWRITE'); % open file + var = 'inquirying data'; + [numdims,numvars,numglob] = netcdf.inq(ncid); % get number of anything + + % ----- GLOBAL ATTRIBUTES -------------------------------------------- + for ii=0:numglob-1 + var = netcdf.inqAttName(ncid,globid,ii); + Obj.([glob var]) = netcdf.getAtt(ncid,globid,var); + end + + % ----- DIMENSIONS --------------------------------------------------- + dimids = netcdf.inqDimIDs(ncid); + dims = cell(numdims,1); % cell array with dimension names + startp = zeros(numdims,1); % vector with start of a dimension + countp = zeros(numdims,1); % vector with the element count in a dimension + for ii=0:numdims-1 + [var,len] = netcdf.inqDim(ncid,dimids(ii+1)); + Obj.API.(var) = len; + dims{ii+1} = var; + startp(ii+1) = 0; + countp(ii+1) = len; + end + Dims = cell2mat(dims)'; + + % Check the requested measurements + if isnumeric(flags) + partialDimRange = flags; + partialDim = varargin{1}; + for ii=1:length(partialDim) + if Obj.API.(partialDim(ii))<(sum(partialDimRange(ii,:))-1) + error('Requested indices exceed measurement count'); + end; + startp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,1)-1; + countp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,2); + end + end + + + % ----- VARIABLES + ATTRIBUTES --------------------------------------- + varids = netcdf.inqVarIDs(ncid); + for ii=0:numvars-1 + [var,~,vardimids,natts] = netcdf.inqVar(ncid,varids(ii+1)); + % Data + if strfind(var,'Data.'), + if ~strcmp(flags,'nodata') + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.Data.(var(6:end))=dim; + if strfind(dim,'S') % strings + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.Data.(var(6:end))=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.Data.(var(6:end))(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.Data.(var(6:end))=cellstr(reshape(reshape(data,1,[]),size(data,2),[])); + end + elseif length(dim)>1 + Obj.Data.(var(6:end))=permute(netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)), length(dim):-1:1); + else + Obj.Data.(var(6:end))=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + end + end + % Variables + else + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.(var)=dim; + if strfind(dim,'S') + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.(var)=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.(var)(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.(var)=cellstr(reshape(reshape(data,1,[]),size(data,2),[])); + end + elseif length(dim)>1 + Obj.(var)=permute(data, length(dim):-1:1); + else + Obj.(var)=data; + end + end + + if natts + for jj=0:natts-1 + att = netcdf.inqAttName(ncid,varids(ii+1),jj); + attval = netcdf.getAtt(ncid,varids(ii+1),att); + if strfind(var,'Data.'), Obj.Data.([var(6:end) '_' att])=attval; else Obj.([var '_' att])=attval; end + end + end + end + +catch ME + if exist('ncid','var'); netcdf.abort(ncid); end; + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message 10 'See also the error stack before']); +end + +netcdf.close(ncid); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFsave.m new file mode 100644 index 0000000000000000000000000000000000000000..b2a6b582298e6a4c91f08af55386ea38003d038d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/netcdf/NETCDFsave.m @@ -0,0 +1,177 @@ +function NETCDFsave(filename,Obj,Compression) +%NETCDFSAVE +% NETCDFsave(filename,Dataset,Compression) saves all data and metadata to +% a SOFA file. + +% SOFA API - function netcdf/NETCDFsave +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Piotr Majdak, 9.4.2013 + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob='GLOBAL_'; +% Dims='IRENMCQ'; % dimensions + +globid=netcdf.getConstant('GLOBAL'); + +try + var='file creation'; + mode = netcdf.getConstant('NETCDF4'); +% mode = netcdf.getConstant('clobber'); +% mode = bitor(mode,netcdf.getConstant('CLASSIC_MODEL')); + ncid = netcdf.create(filename,mode); + +%% Save global attributes + f=fieldnames(Obj); + + for ii=1:length(f) + if ~isempty(strfind(f{ii},glob)) + var=f{ii}; + netcdf.putAtt(ncid,globid,var(strfind(var,glob)+length(glob):end),Obj.(var)); + end + end + +%% Define dimensions + + Dims=cell2mat(fieldnames(rmfield(Obj.API,'Dimensions'))'); + dimid=nan(size(Dims)); + dimsize=nan(size(Dims)); + for ii=1:length(Dims) + var=Dims(ii); + dimid(ii) = netcdf.defDim(ncid,Dims(ii),Obj.API.(var)); + dimsize(ii)=Obj.API.(var); + end + Sdim=strfind(Dims,'S'); % find the index with string dimension + if isempty(Sdim), Sdim=-1, end; % mark as -1 if not existing + +%% Define metadata variables and their attributes +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varId(ii),true,true,Compression); + for jj=1:length(f) + if ~isempty(strfind(f{jj},[var '_'])) + netcdf.putAtt(ncid,varId(ii),f{jj}(strfind(f{jj},[var '_'])+length([var '_']):end),Obj.(f{jj})); + end + end + end + end + +%% Define data variables and their attributes +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varIdD(ii),true,true,Compression); + for jj=1:length(fod) + if ~isempty(strfind(fod{jj},[var '_'])) + netcdf.putAtt(ncid,varIdD(ii),fod{jj}(strfind(fod{jj},[var '_'])+length([var '_']):end),Obj.Data.(fod{jj})); + end + end + end + end + +%% End of definition + netcdf.endDef(ncid); + +%% Save metadata variables +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if length(ids)>1 + if iscell(Obj.(var)) + c=char(permute(Obj.(var),length(ids):-1:1)); + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),permute(Obj.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.(var)) + c=char(Obj.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),Obj.(var)); + end + end + end + end + +%% Save data variables +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if length(ids)>1 + if iscell(Obj.Data.(var)) + c=char(permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.Data.(var)) + c=char(Obj.Data.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),Obj.Data.(var)); + end + end + end + end + +catch ME +% if ~strcmp(ME.identifier,'MATLAB:imagesci:netcdf:libraryFailure') + netcdf.close(ncid); +% end + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message]); + +end +netcdf.close(ncid); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..2d747d62797da1b30fc3851bfa2f2488b0b5ef86 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/readme.txt @@ -0,0 +1,17 @@ +This is a readme file for the SOFA API for Matlab and Octave. + +* When adding SOFA API to Matlab search path: Use "Add Folder", don't use "Add with Subfolders" +* Start the API: execute "SOFAstart" in Matlab or Octave. +* No HRTF files to play around? Follow the advices in the readme.txt files in the HRTFs directories. +* Explore the API: execute some of the "demo_" files in the directory "demos". +* Learn more about SOFA: read the specs PDF in the directory "doc". +* Report a bug: send a ticket at https://sf.net/p/sofacoustics/. +* Last changes? check the file "history.txt". + +Tested with Matlab R2013a (and higher) and Octave 3.6. + +Contact the main developer: Piotr Majdak <piotr@majdak.com>. +Many thanks go to Hagen Wierstorf <hagen.wierstorf@tu-berlin.de> for the Octave support. + +Acoustics Research Insitute (ARI) +Austrian Academy of Sciences (OeAW) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/test/test_SOFAall.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/test/test_SOFAall.m new file mode 100644 index 0000000000000000000000000000000000000000..7444beb9073d012d464aca06478eef381cb7a2dc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/API_MO/test/test_SOFAall.m @@ -0,0 +1,98 @@ +% SOFA API - test script +% Test some of the SOFA API functionality + +% Copyright (C) 2012-2013 Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.1 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: http://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +clc; +warning('off','SOFA:upgrade'); + +%% Test converters to SOFA +disp('********************************************'); +clear all; +subjectID='NH4'; +demo_ARI2SOFA +subjectID='NH2'; +demo_ARI2SOFA + +clear all; +demo_CIPIC2SOFA; + +clear all; +subjectID='1002'; +demo_LISTEN2SOFA; + +clear all; +pinna='normal'; +demo_MIT2SOFA; +pinna='large'; +demo_MIT2SOFA; + +clear all; +radius=[0.5 1 2 3]; +demo_TUBerlin2SOFA; + +clear all; +if ~exist('OCTAVE_VERSION','builtin'), demo_FHK2SOFA; end + +clear all; +demo_BTDEI2SOFA; + +%% Test converters from SOFA +disp('********************************************'); +clear all; +demo_SOFA2ARI; +% SOFAplotGeometry(Obj); + +%% Test SOFAmerge and create TU-Berlin KEMAR file with multiple radii +disp('********************************************'); +clear all; +demo_SOFAmerge; + +%% Test SOFAload +disp('********************************************'); +clear all; +demo_SOFAload; + +%% Test SOFAspat, but do not play +disp('********************************************'); +clear all; +dontplay=1; +demo_SOFAspat; + +%% Test SOFAexpand and SOFAcompact +disp('********************************************'); +clear all; +demo_SOFAexpandcompact; + +%% Test SOFAsave +disp('********************************************'); +clear all; +demo_SOFAsave; + +%% Test convertions from SimpleFreeFieldHRIR to SimpleFreeFieldTF +disp('********************************************'); +clear all; +demo_SimpleFreeFieldHRIR2TF; + +%% Test SingleRoomDRIR +disp('********************************************'); +clear all +demo_SingleRoomDRIROldenburg; + +%% Test variables handling +disp('********************************************'); +demo_SOFAvariables + +%% Test plotting HRTFs +disp('********************************************'); +demo_SOFAplotHRTF + +%% Demo of headphone conventions +demo_HpIR +%% Test using string arrays +demo_SOFAstrings \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/ARI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/ARI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..1f826fea730bd634928f605a8f5d025cb0df9c12 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/ARI/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the ARI database, http://www.kfs.oeaw.ac.at/hrtf +The data must be in the format as downloaded from ARI, that is NHX\hrtf_M_dtf 256.mat where NHX is the ARI subject ID. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/BTDEI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/BTDEI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba118e57056213ea47599e974a08bb1c3d1fc175 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/BTDEI/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the BT-DEI database, http://padva.dei.unipd.it/?page_id=345 +The data must be in the format as downloaded from BT-DEI, that is HXXX\SYYY\... where XXX is the headphone type and YYY the subject ID (three digits each). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/CIPIC/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/CIPIC/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..555fb6fde373d0e9838e23684a554d0ef7e0ec47 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/CIPIC/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the CIPIC database, http://interface.cipic.ucdavis.edu/data/CIPIC_hrtf_database.zip +The data must be in the format as downloaded from CIPIC, that is subject_XXX\hrir_final.mat where XXX is the CIPIC subject ID (three digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/FHK/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/FHK/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..1be7fba29b114ff59a967d5571c4b72d36ffaded --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/FHK/readme.txt @@ -0,0 +1,5 @@ +Save here the HRTF data from the FHK database, http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +The data must be in the format as downloaded from the server, i.e., HRIR_*.mat + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/LISTEN/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/LISTEN/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..83cc0f5ad0b95a934dd44d63904e440c278edbeb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/LISTEN/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the LISTEN database, http://recherche.ircam.fr/equipes/salles/listen/download.html +The data must be in the format as downloaded from IRCAM, that is IRC_XXXX\COMPENSATED\MAT\HRIR\IRC_XXX_C_HRIR.mat where XXXX is the LISTEN subject ID (4 digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/MIT KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/MIT KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..feb4a69d479a4ef84b7fea7bc5042533c31ec204 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/MIT KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the MIT database, http://sound.media.mit.edu/resources/KEMAR/full.zip +The data must be the "full" data as downloaded from MIT, that is full\elevE\PEeAa.wav where A and E is the azimuth and the elevation angles, respectively, and P is the pinna used, that is, L (normal pinna) or (large pinna). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/Oldenburg/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/Oldenburg/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..85709e35dfc0354dae14e3a203fcc41f607c73a2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/Oldenburg/readme.txt @@ -0,0 +1,6 @@ +Save here the data from the Oldeburg database, http://sirius.physik.uni-oldenburg.de/downloads/hrir/HRIR_database_mat.zip + +Note: before downloading that using that data, you must go to http://medi.uni-oldenburg.de/hrir/html/download.html and accept the form. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SCUT/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SCUT/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..a1cfbef2581b7503002efd3e57ac41d986efefc7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SCUT/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the SCUT database (Bosun Xie, Ghongzhou, China) +The data must be in the format as provided by the SCUT, e.g., the nearfield KEMAR data in the directory "nearfield". + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SOFA/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SOFA/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..7270aa38aa0f9978e68abd057e0c8fcae913d5d4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SOFA/readme.txt @@ -0,0 +1,7 @@ +SOFA files go here. + +When used with the default settings of SOFAdbURL and SOFAdbPath, this directory reflects http://www.sofacoustics.org/data/ + + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SOFA/sofa_api_mo_test/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SOFA/sofa_api_mo_test/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..000cb3818f4f4e41174f34764f5b44d251c4440f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/SOFA/sofa_api_mo_test/readme.txt @@ -0,0 +1,8 @@ +SOFA files go here. They can be + +* manually downloaded by you from http://tinyurl.com/sofaHRTFs +* automatically created by the API by demo_ functions when the source HRTFs are available +* automatically downloaded by the API from http://www.sofacoustics.org/data/sofa_api_mo_test when requested and available + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/TU-Berlin KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/TU-Berlin KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..c2acdd82fc2c7af0e42aa97fa030797ee1294ca3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/HRTFs/TU-Berlin KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the TU-Berlin database, https://dev.qu.tu-berlin.de/projects/measurements/repository/show/2010-11-kemar-anechoic/mat +The data must be in the format as downloaded from TU Berlin. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/README.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/README.md new file mode 100644 index 0000000000000000000000000000000000000000..31204a9f7a494e74d57aaf1514432129024cf2ec --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/README.md @@ -0,0 +1,65 @@ +SOFA - Spatially Oriented Format for Acoustics +============================================== + +SOFA is a file format for reading, saving, and describing spatially +oriented data of acoustic systems. + +Examples of data we consider are head-related transfer functions (HRTFs), +binaural room impulse responses (BRIRs), multichannel measurements such as done +with microphone arrays, or directionality data of loudspeakers. + +The format specifications are the major issue, but we also aim in providing APIs +for reading and writing the data in SOFA. + +For more information on the format specifications and available data have a look +at http://www.sofaconventions.org/ + + +Downloads +========= + +Current versions of SOFA can be found on its [old +home](http://sourceforge.net/projects/sofacoustics/files/?source=navbar). + +At the moment we are working on a new release which will be shortly available on +this site. + + +Usage +===== + +## Matlab/Octave API + +In order to use SOFA with Matlab or Octave you have to add its `API_MO` folder +to your paths. After that you can play around with your acoustic measurements +as shown by the following example which uses a head-related transfer function +measurement. + +```matlab +% Start SOFA +SOFAstart; +% Load your impulse response into a struct +hrtf = SOFAload('path/to_your/HRTF.sofa')); +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +size(hrtf.Data.IR) +% Get information about the measurement setup +hrtf.ListenerPosition % position of dummy head +hrtf.SourcePosition % position of loudspeaker +% Head orientation of the dummy head + coordinate system and units +hrtf.ListenerView +hrtf.ListenerView_Type +hrtf.ListenerView_Units +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundInput = audioread('fancy_audio_file.wav'); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); +``` diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/doc/API_MO 1.0.pdf b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/doc/API_MO 1.0.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e6a1ef6693239599664288e4cd9776177a7ac738 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/doc/API_MO 1.0.pdf differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/doc/SOFA specs 0.6.pdf b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/doc/SOFA specs 0.6.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1f267603045b130ff8e8d39cd9cdb0bf0c785b77 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/doc/SOFA specs 0.6.pdf differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/license.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..5a4050fd1bd02f1379742034c341bb980fc18560 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFA_API_Matlab_Octave/license.txt @@ -0,0 +1,311 @@ +European Union Public Licence +V. 1.1 + + +EUPL © the European Community 2007 + + +This European Union Public Licence (the “EUPL”) applies to the +Work or Software (as defined below) which is provided under the terms of this +Licence. Any use of the Work, other than as authorised under this Licence is +prohibited (to the extent such use is covered by a right of the copyright +holder of the Work). + +The Original Work is provided under the terms of this +Licence when the Licensor (as defined below) has placed the following notice +immediately following the copyright notice for the Original Work: + +Licensed under the EUPL V.1.1 + +or has expressed by any other mean his willingness to license under the EUPL. + + +1. Definitions + +In this Licence, the +following terms have the following meaning: + +- The Licence: this Licence. + +- The Original Work or the Software: the software distributed +and/or communicated by the Licensor under this Licence, available as Source +Code and also as Executable Code as the case may be. + +- Derivative Works: +the works or software that could be created by the Licensee, based upon the +Original Work or modifications thereof. This Licence does not define the +extent of modification or dependence on the Original Work required in order to +classify a work as a Derivative Work; this extent is determined by copyright +law applicable in the country mentioned in Article 15. + +- The Work: the Original Work and/or its Derivative Works. + +- The Source Code: the human-readable form of the Work which is the most +convenient for people to study and modify. + +- The Executable Code: any code which has generally been compiled and which +is meant to be interpreted by a computer as a program. + +- The Licensor: the natural or legal person that distributes and/or +communicates the Work under the Licence. + +- Contributor(s): any natural or legal person who modifies the Work under the +Licence, or otherwise contributes to the creation of a Derivative Work. + +- The Licensee or “You”: any natural or legal person who makes any usage of +the Software under the terms of the Licence. + +- Distribution and/or Communication: any act of selling, giving, lending, +renting, distributing, communicating, transmitting, or otherwise +making available, on-line or off-line, copies of the Work or providing access +to its essential functionalities at the disposal of any other natural or legal +person. + + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a world-wide, royalty-free, non-exclusive, +sub-licensable licence to do the following, for the duration of copyright +vested in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Original Work, and make Derivative Works +based upon the Work, +- communicate to the public, including the right to make available or display +the Work or copies thereof to the public and perform publicly, as the case +may be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sub-license rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make +effective the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non exclusive usage rights +to any patents held by the Licensor, to the extent necessary to make use of +the rights granted on the Work under this Licence. + + +3. Communication of the Source Code + +The Licensor may provide the Work either +in its Source Code form, or as Executable Code. If the Work is provided as +Executable Code, the Licensor provides in addition a machine-readable copy of +the Source Code of the Work along with each copy of the Work that the Licensor +distributes or indicates, in a notice following the copyright notice attached +to the Work, a repository where the Source Code is easily and freely +accessible for as long as the Licensor continues to distribute and/or +communicate the Work. + + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits +from any exception or limitation to the exclusive rights of the rights owners +in the Original Work or Software, of the exhaustion of those rights or of +other applicable limitations thereto. + + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: +the Licensee shall keep intact all copyright, patent or trademarks notices and +all notices that refer to the Licence and to the disclaimer of warranties. The +Licensee must include a copy of such notices and a copy of the Licence with +every copy of the Work he/she distributes and/or communicates. The Licensee +must cause any Derivative Work to carry prominent notices stating that the +Work has been modified and the date of modification. + +Copyleft clause: +If the Licensee distributes and/or communicates copies of the Original Works +or Derivative Works based upon the Original Work, this Distribution and/or +Communication will be done under the terms of this Licence or of a later +version of this Licence unless the Original Work is expressly distributed only +under this version of the Licence. The Licensee (becoming Licensor) cannot +offer or impose any additional terms or conditions on the Work or Derivative +Work that alter or restrict the terms of the Licence. + +Compatibility clause: +If the Licensee Distributes and/or Communicates Derivative Works or copies +thereof based upon both the Original Work and another work licensed under a +Compatible Licence, this Distribution and/or Communication can be done under +the terms of this Compatible Licence. For the sake of this clause, +“Compatible Licence” refers to the licences listed in the appendix +attached to this Licence. Should the Licensee’s obligations under the +Compatible Licence conflict with his/her obligations under this Licence, the +obligations of the Compatible Licence shall prevail. + +Provision of Source Code: +When distributing and/or communicating copies of the Work, the Licensee +will provide a machine-readable copy of the Source Code or indicate a +repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute and/or communicate the Work. + +Legal Protection: +This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work +granted hereunder is owned by him/her or licensed to him/her and +that he/she has the power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she +brings to the Work are owned by him/her or licensed to him/her and that +he/she has the power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under +the terms of this Licence. + + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +contributors. It is not a finished work and may therefore contain defects or +“bugs” inherent to this type of software development. + +For the above reason, the Work is provided under the Licence on an “as is” +basis and without warranties of any kind concerning the Work, including +without limitation merchantability, fitness for a particular purpose, absence +of defects or errors, accuracy, non-infringement of intellectual property +rights other than copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a +condition for the grant of any rights to the Work. + + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to +natural persons, the Licensor will in no event be liable for any direct or +indirect, material or moral, damages of any kind, arising out of the Licence +or of the use of the Work, including without limitation, +damages for loss of goodwill, work stoppage, computer failure or malfunction, +loss of data or any commercial damage, even if the Licensor has been advised +of the possibility of such damage. However, the Licensor will be liable under +statutory product liability laws as far such laws apply to the Work. + + +9. Additional agreements + +While distributing the Original Work or Derivative Works, You may choose +to conclude an additional agreement to offer, and charge a fee for, +acceptance of support, warranty, indemnity, or other liability +obligations and/or services consistent with this Licence. However, in +accepting such obligations, You may act only on your own behalf and on your +sole responsibility, not on behalf of the original Licensor or any other +Contributor, and only if You agree to indemnify, defend, and hold each +Contributor harmless for any liability incurred by, or claims asserted against +such Contributor by the fact You have accepted any such warranty or additional +liability. + + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on +an icon “I agree” placed under the bottom of a window displaying the text of +this Licence or by affirming consent in any other similar way, in accordance +with the rules of applicable law. Clicking on that icon indicates your clear +and irrevocable acceptance of this Licence and +all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and +all of its terms and conditions by exercising any rights granted to You +by Article 2 of this Licence, such as the use of the Work, +the creation by You of a Derivative Work or the Distribution and/or +Communication by You of the Work or copies thereof. + + +11. Information to the public + +In case of any Distribution and/or Communication of the Work by means of +electronic communication by You (for example, by offering to download +the Work from a remote location) the distribution channel or media (for +example, a website) must at least provide to the public the information +requested by the applicable law regarding the Licensor, the Licence and the +way it may be accessible, concluded, stored and reproduced by the +Licensee. + + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically +upon any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work licensed hereunder. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed and/or reformed so as necessary +to make it valid and enforceable. + +The European Commission may publish other linguistic versions and/or new +versions of this Licence, so far this is required and reasonable, without +reducing the scope of the rights granted by the Licence. +New versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version +of their choice. + + +14. Jurisdiction + +Any litigation resulting from the interpretation of this License, arising +between the European Commission, as a Licensor, and any Licensee, +will be subject to the jurisdiction of the Court of Justice of the +European Communities, as laid down in article 238 of the Treaty establishing +the European Community. + +Any litigation arising between Parties, other than the European Commission, +and resulting from the interpretation of this License, will be subject to the +exclusive jurisdiction of the competent court where the Licensor resides or +conducts its primary business. + + +15. Applicable Law + +This Licence shall be governed by the law of the European Union country where +the Licensor resides or has his registered office. + +This licence shall be governed by the Belgian law if: + +- a litigation arises between the European Commission, as a Licensor, and any +Licensee; +- the Licensor, other than the European Commission, has no residence or +registered office inside a European Union country. + + +=== + + +Appendix + + +“Compatible Licences” according to article 5 EUPL are: +- GNU General Public License (GNU GPL) v. 2 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Common Public License v. 1.0 +- Eclipse Public License v. 1.0 +- Cecill v. 2.0 diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master.zip b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master.zip new file mode 100644 index 0000000000000000000000000000000000000000..3ea99ef28aeff00a25f65a8393ad885b23f111b0 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master.zip differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/.gitignore b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..435fa576cc1042465f4f7006aedb932c430c1500 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/.gitignore @@ -0,0 +1,27 @@ +# compiled convention files +/SOFAtoolbox/conventions/*.mat +/SOFAtoolbox/conventions/*.txt +# test files for demos +/SOFAtoolbox/demos/*.sofa +/SOFAtoolbox/demos/demo_FreeFieldHRTF/*.fig +/SOFAtoolbox/demos/demo_FreeFieldHRTF/*.png +/SOFAtoolbox/demos/LigetiHall_CubeletToSt450/ +/SOFAtoolbox/test/*.sofa +/SOFAtoolbox/test/*/*.wav +/SOFAtoolbox/test/LigetiHall_CubeletToSt450/ +/HRTFs/ARI/*/*.mat +/HRTFs/BTDEI/*/*/*/*/*/*.mat +/HRTFs/BTDEI/*/headphones_info.mat +/HRTFs/CIPIC/*/*.mat +/HRTFs/CIPIC/show_data/ +/HRTFs/CIPIC/CIPIC_hrtf_database/ +/HRTFs/FHK/*.mat +/HRTFs/LISTEN/IRC_1002/ +/HRTFs/MIT KEMAR/full/*/*.wav +/HRTFs/Oldenburg/HRIR_database_mat/ +/HRTFs/SCUT/nearfield/ +/HRTFs/SOFA/sofatoolbox_test/*.sofa +/HRTFs/SOFA/database/*/*.sofa +/HRTFs/SOFA/headphones/*/*.sofa +/HRTFs/TU-Berlin KEMAR/*.mat +/SOFAtoolbox/helpers/*.m diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/ARI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/ARI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..c0aaf14e32a9d4ceb1688ae739a6c25805c7e813 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/ARI/readme.txt @@ -0,0 +1,7 @@ +Save here the data from the ARI database, http://www.oeaw.ac.at/isf/hrtf +Direct link to ARI database: https://projects.ari.oeaw.ac.at/research/experimental_audiology/hrtf/database/hrtfItEARI.html + +The data must be in the format as downloaded from ARI, that is NHX\hrtf_M_dtf 256.mat where NHX is the ARI subject ID. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/BTDEI/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/BTDEI/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ba118e57056213ea47599e974a08bb1c3d1fc175 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/BTDEI/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the BT-DEI database, http://padva.dei.unipd.it/?page_id=345 +The data must be in the format as downloaded from BT-DEI, that is HXXX\SYYY\... where XXX is the headphone type and YYY the subject ID (three digits each). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/CIPIC/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/CIPIC/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..e7552e82e844afc7300366d1f23b91d431a4c9d2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/CIPIC/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the CIPIC database, https://www.ece.ucdavis.edu/cipic/spatial-sound/hrtf-data/ [link obsolete!] +The data must be in the format as downloaded from CIPIC, that is subject_XXX\hrir_final.mat where XXX is the CIPIC subject ID (three digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/FHK/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/FHK/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..1be7fba29b114ff59a967d5571c4b72d36ffaded --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/FHK/readme.txt @@ -0,0 +1,5 @@ +Save here the HRTF data from the FHK database, http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +The data must be in the format as downloaded from the server, i.e., HRIR_*.mat + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/LISTEN/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/LISTEN/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..83cc0f5ad0b95a934dd44d63904e440c278edbeb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/LISTEN/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the LISTEN database, http://recherche.ircam.fr/equipes/salles/listen/download.html +The data must be in the format as downloaded from IRCAM, that is IRC_XXXX\COMPENSATED\MAT\HRIR\IRC_XXX_C_HRIR.mat where XXXX is the LISTEN subject ID (4 digits). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/MIT KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/MIT KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..feb4a69d479a4ef84b7fea7bc5042533c31ec204 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/MIT KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the MIT database, http://sound.media.mit.edu/resources/KEMAR/full.zip +The data must be the "full" data as downloaded from MIT, that is full\elevE\PEeAa.wav where A and E is the azimuth and the elevation angles, respectively, and P is the pinna used, that is, L (normal pinna) or (large pinna). + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/Oldenburg/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/Oldenburg/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..85709e35dfc0354dae14e3a203fcc41f607c73a2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/Oldenburg/readme.txt @@ -0,0 +1,6 @@ +Save here the data from the Oldeburg database, http://sirius.physik.uni-oldenburg.de/downloads/hrir/HRIR_database_mat.zip + +Note: before downloading that using that data, you must go to http://medi.uni-oldenburg.de/hrir/html/download.html and accept the form. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SCUT/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SCUT/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..a1cfbef2581b7503002efd3e57ac41d986efefc7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SCUT/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the SCUT database (Bosun Xie, Ghongzhou, China) +The data must be in the format as provided by the SCUT, e.g., the nearfield KEMAR data in the directory "nearfield". + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SOFA/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SOFA/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..7270aa38aa0f9978e68abd057e0c8fcae913d5d4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SOFA/readme.txt @@ -0,0 +1,7 @@ +SOFA files go here. + +When used with the default settings of SOFAdbURL and SOFAdbPath, this directory reflects http://www.sofacoustics.org/data/ + + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SOFA/sofatoolbox_test/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SOFA/sofatoolbox_test/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..458ab5cc8fb3332208879a114c34cc4a7754e885 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/SOFA/sofatoolbox_test/readme.txt @@ -0,0 +1,8 @@ +SOFA files go here. They can be + +* manually downloaded by you from http://tinyurl.com/sofaHRTFs +* automatically created by the Toolbox by demo_ functions when the source HRTFs are available +* automatically downloaded by the Toolbox from http://www.sofacoustics.org/data/sofatoolbox_test when requested and available + +SOFA Toolbox for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/TU-Berlin KEMAR/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/TU-Berlin KEMAR/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..f80db755519a8b4da271e7c23edef97010027dcd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/HRTFs/TU-Berlin KEMAR/readme.txt @@ -0,0 +1,5 @@ +Save here the data from the TU-Berlin database, https://doi.org/10.5281/zenodo.4459911 +The data must be in the format as downloaded from TU Berlin. + +SOFA API for Matlab and Octave +Piotr Majdak, ARI, OeAW diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/README.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/README.md new file mode 100644 index 0000000000000000000000000000000000000000..a9b1f711153bd443cad060444125bb484ecb0f27 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/README.md @@ -0,0 +1,64 @@ +SOFA - Spatially Oriented Format for Acoustics +============================================== + +SOFA is a file format for reading, saving, and describing spatially +oriented data of acoustic systems. + +Examples of data we consider are head-related transfer functions (HRTFs), +binaural room impulse responses (BRIRs), multichannel measurements such as done +with microphone arrays, or directionality data of loudspeakers. + +The format specification is the major focus of SOFA, but we also aim in providing +toolboxes for reading and writing the data in SOFA. For more information on the +format specifications and available data, see http://www.sofaconventions.org/. + +This project implements a reference toolbox for SOFA: The SOFA Toolbox. + +SOFA Toolbox 2.x implements SOFA versions 2.x. The SOFA Toolbox has been previously +known as the SOFA API_MO, which supported SOFA versions up to 1.x. + + +Downloads +========= + +Current releases of SOFA Toolbox can be found on its [old +home](http://sourceforge.net/projects/sofacoustics/files/?source=navbar). + +**Note:** +- The currently latest release is known as the SOFA API M/O version 1.1.3. +- The SOFA Toolbox 2.0 has never been released. +- The SOFA Toolbox 2.1 is currently under preparation. It will support SOFA 2.1 as known as AES69-2022. + + +Usage +===== + +## Matlab/Octave + +In order to use SOFA with Matlab or Octave add its `SOFAtoolbox` folder +to your search paths. After that you can play around with your acoustic measurements +as shown by the following example which uses a HRTF measurement. + +```matlab +%% put your information here: +hrtf = SOFAload('path/to_your/HRTF.sofa'); +soundInput = audioread('path/to_your/fancy_audio_file.wav'); + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(hrtf.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); +``` diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..dda2380db8f49f5f33175cf59d42dd0b3c23be07 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAaddVariable.m @@ -0,0 +1,61 @@ +function Obj = SOFAaddVariable(Obj,Name,Dim,Value) +%SOFAaddVariable +% Obj = SOFAaddVariable(Obj,Name,Dim,Value) adds a user-defined variable +% to the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). DIM is a string +% describing the dimensions of the variable according to SOFA specifications. +% The content of NAME is stored in VALUE which must be of the size DIM. +% The used-defined variable NAME will be stored as Obj.NAME and its +% dimension will be stored as Obj.API.Dimensions.NAME. Note that user- +% defined variables can be saved in SOFA file and thus remain in the +% object when loaded from a SOFA file. +% +% Obj = SOFAaddVariable(Obj,Name,'PRIVATE',Value) adds a private variable +% to OBJ. The private variable NAME will be stored as Obj.PRIVATE.NAME. +% Note that the private variables will be not stored in SOFA files and +% arbitrary dimensions are allowed. +% +% Note that adding variables to Data is not supported and should not be used +% as it might be confusing having user-defined variables in a Data structure. +% Consider adding a variable at the global level instead, which would be more +% clear for others. + +% #Author: Piotr Majdak +% #Author: Piotr Majdak: dimension is added if not previously found. (9.8.2014) +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAaddVariable +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Dim=upper(Dim); +switch Dim + case 'PRIVATE' + Obj.PRIVATE.(Name)=Value; + otherwise + switch Name + case {'API','PRIVATE','GLOBAL'} + error('This variable name is reserved.'); + otherwise + if strncmp(Name,'Data.',length('Data.')) + % add variable to Data + Name=Name(length('Data.')+1:end); + Obj.Data.(Name)=Value; + Obj.API.Dimensions.Data.(Name)=Dim; + else + % add variable to root + Obj.(Name)=Value; + Obj.API.Dimensions.(Name)=Dim; + end + dims=SOFAdefinitions('dimensions'); + for ii=1:length(Dim) + if ~isfield(dims,Dim(ii)) + error('Dimension not supported.'); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m new file mode 100644 index 0000000000000000000000000000000000000000..4cd1e5367374580beb8290071fd3c9d3099dca5e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAappendText.m @@ -0,0 +1,27 @@ +function output = SOFAappendText(Obj,attribute,new) +%SOFAappendText +% +% output = SOFAappendText(Obj,attribute,new) appends the new text to the +% attribute (as string) using the correct SOFA separators. If the attribute is empty +% or non-existing, the output will be the new text only. +% +% example: +% Obj.GLOBAL_Title = SOFAappendText(Obj, 'GLOBAL_Title', 'Append me to the title.'); + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAappendText +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~isfield(Obj,attribute), Obj.(attribute)=''; end +if isempty(Obj.(attribute)), + output=new; +else + output=[Obj.(attribute) SOFAdefinitions('EOL') new]; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m new file mode 100644 index 0000000000000000000000000000000000000000..7699a5664ee60e26c72ffdf90259d9f72db1aa2c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAarghelper.m @@ -0,0 +1,273 @@ +function [flags,keyvals,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun) +%SOFAARGHELPER Parse arguments for SOFA +% Usage: [flags,keyvals,varargout] = SOFAarghelper(posdepnames,definput,arglist,callfun); +% +% Input parameters: +% posdepnames : Names of the position dependant parameters. +% definput : Struct to define the allowed input +% arglist : Commandline of the calling function (varargin) +% callfun : Name of calling function (optional) +% +% Output parameters: +% flags : Struct with information about flags. +% keyvals : Struct with key / values. +% varargout : The position dependant pars. properly initialized +% +% [flags,keyvals,varargout]=SOFAarghelper(posdepnames,definput,arglist,callfun) assists in +% parsing input parameters for a function. Parameters come in +% four categories: +% +% Position dependant parameters. These must not be strings. These are +% the first parameters passed to a function, and they are really just a short way +% of specifying key/value pairs. See below. +% +% Flags. These are single string appearing after the position dependant +% parameters. +% +% Key/value pairs. The key is always a string followed by the value, which can be +% anything. +% +% Expansions. These appear as flags, that expand into a pre-defined list of parameters. +% This is a short-hand way of specifying standard sets of flags and key/value pairs. +% +% The parameters are parsed in order, so parameters appearing later in varargin will override +% previously set values. +% +% The following example for calling SOFAARGHELPER is taken from DGT: +% +% definput.keyvals.L=[]; +% definput.flags.phase={'freqinv','timeinv'}; +% [flags,kv]=SOFAarghelper({'L'},definput,varargin); +% +% The first line defines a key/value pair with the key 'L' having an initial value of `[]` +% (the empty matrix). +% +% The second line defines a group of flags by the name of phase. The +% group phase contains the flags `'freqinv'` and `'timeinv'`, which can +% both be specified on the command line by the user. The group-name +% phase is just for internal use, and does not appear to the user. The +% flag mentioned first in the list will be selected by default, and only +% one flag in a group can be selected at any time. A group can contain as +% many flags as desired. +% +% The third line is the actual call to SOFAARGHELPER which defines the +% output flags and `kv`. The input `{'L'}` indicates that the value of +% the parameter 'L' can also be given as the very first value in +% varargin. +% +% The output struct kv contains the key/value pairs, so the value associated to `'L'` is +% stored in kv.L. +% +% The output struct flags contains information about the flags choosen +% by the user. The value of flags.phase will be set to the selected flag +% in the group phase and additionally, the value of `flags.do_timeinv` +% will be 1 if 'timeinv' was selected and 0 otherwise, and similarly for +% 'freqinv'. This allows for easy checking of selected flags. +% + +% #Author: Peter L. Soendergaard, Copyright (C) 2005-2012 +% #Author: Piotr Majdak: Modified from the LTFAT 1.1.2 for SOFA by Piotr Majdak. +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. + +persistent SOFA_CONF; + +if isempty(SOFA_CONF) + SOFA_CONF.fundefs = struct; +end; + +if ischar(posdepnames) + % Special interface needed for ltfatsetdefaults and ltfatgetdefaults, + % activated when first argument is a string. + + % First input argument, posdepnames, is a string, one of the options + % in the "switch" section below + % Second input argument, definput, is a function name to get or set + % Third input argument, arglist , is a cell-array with options to set. + + switch(lower(posdepnames)) + case 'get' + if isfield(SOFA_CONF.fundefs,definput) + flags=SOFA_CONF.fundefs.(definput); + else + flags={}; + end; + case 'set' + SOFA_CONF.fundefs.(definput)=arglist; + case 'all' + flags=SOFA_CONF.fundefs; + case 'clearall' + SOFA_CONF.fundefs=struct; + end; + return +end; + +if nargin<4 + f=dbstack; + callfun=f(2).name; +end; + +nposdep=numel(posdepnames); + +% Resolve import specifications BEFORE adding our own specifications. +if isfield(definput,'import') + for imp = definput.import; + definput=feval(['arg_',imp{1}],definput); + end; +end; + +if isfield(definput,'flags') + defflags=definput.flags; +else + defflags=struct; +end; + +if isfield(definput,'keyvals') + defkeyvals=definput.keyvals; +else + defkeyvals=struct; +end; + +if isfield(definput,'groups') + groups=definput.groups; +else + groups=struct; +end; + +total_args = numel(arglist); + +% Determine the position of the first optional argument. +% If no optional argument is given, return nposdep+1 +first_str_pos = 1; +while first_str_pos<=total_args && ~ischar(arglist{first_str_pos}) + first_str_pos = first_str_pos +1; +end; + +% If more than nposdep arguments are given, the first additional one must +% be a string +if (first_str_pos>nposdep+1) + error('%s: Too many input arguments',upper(callfun)); +end; + +n_first_args=min(nposdep,first_str_pos-1); + +keyvals=defkeyvals; + +% Copy the given first arguments +for ii=1:n_first_args + keyvals.(posdepnames{ii})=arglist{ii}; +end; + +% Initialize the position independent parameters. +% and create reverse mapping of flag -> group +flagnames=fieldnames(defflags); +flags=struct; +% In order for flags to start with a number, it is necessary to add +% 'x_' before the flag when the flags are used a field names in +% flagreverse. Externally, flags are never used a field names in +% structs, so this is an internal problem in ltfatarghelper that is +% fixed this way. +flagsreverse=struct; +for ii=1:numel(flagnames) + name=flagnames{ii}; + flaggroup=defflags.(name); + flags.(name)=flaggroup{1}; + for jj=1:numel(flaggroup) + flagsreverse.(['x_', flaggroup{jj}])=name; + flags.(['do_',flaggroup{jj}])=0; + end; + flags.(['do_',flaggroup{1}])=1; +end; + +%Get the rest of the arguments +restlist = arglist(first_str_pos:end); + +%Check for default arguments +if isfield(SOFA_CONF.fundefs,callfun) + s=SOFA_CONF.fundefs.(callfun); + restlist=[s,restlist]; +end; + +% Check for import defaults +if isfield(definput,'importdefaults') + % Add the importdefaults before the user specified arguments. + restlist=[definput.importdefaults,restlist]; +end; + +while ~isempty(restlist) + argname=restlist{1}; + restlist=restlist(2:end); % pop + found=0; + + % Is this name a flag? If so, set it + if isfield(flagsreverse,['x_',argname]) + % Unset all other flags in this group + flaggroup=defflags.(flagsreverse.(['x_',argname])); + for jj=1:numel(flaggroup) + flags.(['do_',flaggroup{jj}])=0; + end; + + flags.(flagsreverse.(['x_',argname]))=argname; + flags.(['do_',argname])=1; + found=1; + end; + + % Is this name the key of a key/value pair? If so, set the value. + if isfield(defkeyvals,argname) + keyvals.(argname)=restlist{1}; + restlist=restlist(2:end); + found=1; + end; + + % Is this name a group definition? If so, put the group in front of the parameters + if isfield(groups,argname) + s=groups.(argname); + restlist=[s,restlist]; + found=1; + end; + + % Is the name == 'argimport' + if strcmp('argimport',argname) + fieldnames_flags= fieldnames(restlist{1}); + fieldnames_kvs = fieldnames(restlist{2}); + for ii=1:numel(fieldnames_flags) + importname=fieldnames_flags{ii}; + flags.(importname)=restlist{1}.(importname); + end; + for ii=1:numel(fieldnames_kvs) + importname=fieldnames_kvs{ii}; + keyvals.(importname)=restlist{2}.(importname); + end; + restlist=restlist(3:end); + found=1; + end; + + if found==0 + if ischar(argname) + error('%s: Unknown parameter: %s',upper(callfun),argname); + else + error('%s: Parameter is not a string, it is of class %s',upper(callfun),class(argname)); + end; + end; + + %ii=ii+1; +end; + +% Fill varargout + +varargout=cell(1,nposdep); +for ii=1:nposdep + varargout(ii)={keyvals.(posdepnames{ii})}; +end; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m new file mode 100644 index 0000000000000000000000000000000000000000..bb8c5816c4caf6be538d13a9b96d809a1323411f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateAPV.m @@ -0,0 +1,76 @@ +function ApparentPositionVector = SOFAcalculateAPV(Obj) +%SOFAcalculateAPV +% ApparentPositionVector = SOFAcalculateAPV(Obj) calculates the apparent position vector +% (ApparentPositionVector) which represents the position of the source relative to the +% listener's position and view. ApparentPositionVector is in the format [azi ele radius] +% with units [deg deg m]. +% Note that ListenerUp is not considered and the ApparentPositionVector can be considered as +% the HRTF direction usually used in HRTF databases + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAcalculateAPV +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% === Apparent azimuth === +% Apparent azimuth is the relative direction of the sound source in the +% horizontal plane from the listener viewpoint +% +% Get head orientation of the listener and source position in spherical +% coordinates +HeadOrientation = SOFAconvertCoordinates( ... + Obj.ListenerView,Obj.ListenerView_Type,'spherical'); +SourcePosition = SOFAconvertCoordinates( ... + Obj.SourcePosition,Obj.SourcePosition_Type,'spherical'); +% Calculate the relative azimuth angle between them +APVazimuth = correctAzimuth(bsxfun( ... + @minus,SourcePosition(:,1),HeadOrientation(:,1))); + +% === Apparent elevation === +% Apparent elevation is the relative direction of the sound source in the median +% plane from the listener viewpoint +APVelevation = correctElevation(bsxfun( ... + @minus,SourcePosition(:,2),HeadOrientation(:,2))); + +% === Apparent distance === +% Apparent distance is the relative distance between the sound source and the +% listener +% +% Get listener positon in spherical coordinates +ListenerPosition = SOFAconvertCoordinates( ... + Obj.ListenerPosition,Obj.ListenerPosition_Type,'spherical'); +% Relative distance +APVdistance = bsxfun(@minus,SourcePosition(:,3),ListenerPosition(:,3)); + +% Combine to matrix +ApparentPositionVector = [ ... + APVazimuth, ... + APVelevation, ... + APVdistance, ... +]; + +end + +function phi = correctAzimuth(phi) + % Ensure -360 <= phi <= 360 + phi = rem(phi,360); + % Ensure -180 <= phi < 180 + phi(phi<-180) = phi(phi<-180) + 360; + phi(phi>=180) = phi(phi>=180) - 360; +end + +% TODO: check what convetion we are using for delta! +function delta = correctElevation(delta) + % Ensure -180 <= delta <= 180 + delta = correctAzimuth(delta); + % Ensure -90 <= delta <= 90 + delta(delta<-90) = -delta(delta<-90) - 180; + delta(delta>90) = -delta(delta>90) + 180; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m new file mode 100644 index 0000000000000000000000000000000000000000..a88f7a82c03060ee9080efb62df494aa79d1ee81 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateITD.m @@ -0,0 +1,400 @@ +function [toa_diff,toa,IACC,Obj] = SOFAcalculateITD(Obj,varargin) +% SOFAcalculateITD: Estimate ITD from a binaural signal +% Usage: [toa_diff,toa,IACC,Obj] = SOFAcalculateITD(data,mode,threshlvl,lowpass,butterpoly,upper_cutfreq) +% +% Input parameters: +% +% data: SOFA object or IR matrix with dimensions: +% emitter x receiver x time +% +% fs: sampling rate, used only if data provided as matrix +% +% mode: (optional) Select one estimation methods +% ('Threshold' (default),'Cen_e2','MaxIACCr', 'MaxIACCe', +% 'CenIACCr','CenIACCe', 'CenIACC2e', 'PhminXcor','IRGD') +% +% For details concerning estimation methods see: +% 'http://asa.scitation.org/doi/10.1121/1.4996457' +% +% lowpass: (optional) Bandwidth considered. 'lp' for lowpass (default), 'bb' for broadband +% +% peak: (optional) Method to find the max, used in Threshold mode only. +% 'hp' for max (default), 'fb' for findpeak +% +% threshlvl: (optional) Set threshold level for 'Threshold' mode in dB. +% Default is -10 dB. +% +% butterpoly: (optional) Select the order of the polynom +% applied in the butterworth filter. ( 2 =< i =< 10 ) +% Default is 10. +% +% upper_cutfreq: (optional) Set frequency of lowpass cutoff in Hz. +% Default is 3000 Hz. +% +% lower_cutfreq: (optional) Set frequency of highpass cutoff in Hz, +% only used in IRGD mode. Default is 1000 Hz. +% +% 'debug': (optional, 0/1): Output debug information about calculations. +% +% +% Output parameters: +% +% itd: interaural time difference in seconds +% toa: detected activation onsets for left and right channels +% IACC: interaural cross-correlation coefficient +% Available on when xcorr is used (modes: 'MaxIACCr', 'MaxIACCe', +% 'CenIACCr','CenIACCe', 'CenIACC2e') +% Obj: Input SOFA object with Obj.Data.Delay filled +% +% +% Purpose: +% Estimates the ITD based on biaural impulse responses. +% Several different estimaton methods can be chosen. +% MaxIAACe is recommended. +% +% Requirements: +% ------------- +% +% 1) SOFA Toolbox from http://sourceforge.net/projects/sofacoustics for Matlab (in e.g. thirdparty/SOFA) +% +% +% Examples: +% --------- +% +% Obj = SOFAload(fullfile(SOFAdbPath,'baumgartner2017','hrtf b_nh15.sofa')); +% toa_diff = SOFAcalculateITD(Obj,'MaxIACCe','lp','upper_cutfreq',3000) +% +% With these settings the estimator uses the MaxIAAce method and applies +% a lowpass with a cut off frequency of 3 kHz. +% +% The output array is structured as the SOFA Data.IR +% If you would like to select for example only data on the horizontal +% plane you could: +% +% plane_idx = find( Obj.SourcePosition(:,2) == 0 ); +% plane_angle = Obj.SourcePosition(plane_idx,1); +% +% Url: https://amtoolbox.org/amt-1.0.0/doc/common/itdestimator_code.php + +% #Author: Laurin Steidle +% #Author: Robert Baumgartner: data matrix option +% #Author: Piotr Majdak: Copyright (C) 2009-2021 Piotr Majdak and the AMT team. +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% #Author: Michael Mihocic: adaption for SOFA Toolbox 2.0 +% +% This file is part of the SOFA Toolbox 2.0, +% basing on the function itdestimator in Auditory Modeling Toolbox (AMT) version 1.0.0 +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. + + + + +% ---------------------- SOFAarghelper ------------------------------- +% default parameters (adapted from arg_itdestimator) +definput.keyvals.debug = 0; +definput.flags.mode = {'Threshold','Cen_e2','MaxIACCr', 'MaxIACCe', 'CenIACCr', 'CenIACCe', 'CenIACC2e', 'PhminXcor','IRGD'}; +definput.flags.lp = {'lp','bb'}; +definput.flags.peak = {'hp','fp'}; +definput.flags.toaguess = {'noguess','guesstoa'}; +definput.keyvals.threshlvl = -10; +definput.keyvals.butterpoly = 10; +definput.keyvals.upper_cutfreq = 3000; +definput.keyvals.lower_cutfreq = 1000; +definput.keyvals.avgtoa = 45; +definput.keyvals.fs = []; +definput.keyvals.thr = 20; % dB +definput.keyvals.upsample = 16; % dB +definput.flags.units = {'time', 'samples'}; + +[flags,kv]=SOFAarghelper({},definput,varargin); + +% ---------------------- renaming input parameter --------------------- + +if isstruct(Obj) + pos = Obj.API.M; + ear = Obj.API.R; + Ns = Obj.API.N; + IR = Obj.Data.IR; + fs = Obj.Data.SamplingRate; +else + pos = size(Obj,1); + ear = size(Obj,2); + Ns = size(Obj,3); + IR = Obj; + if isempty(kv.fs) + error('RB: No sampling rate (fs) provided.') + end + fs = kv.fs; +end + +% ---------------------- initialising variables ----------------------- + +toa = zeros(pos,ear); +toa_diff = zeros(pos,1); +IACC = zeros(pos,1); +delay = zeros(length(Obj.SourcePosition), 2); + +if kv.debug == 1; disp('SOFAcalculateITD:'); end + +% ---------------------- Applying low-pass ---------------------------- + +if flags.do_lp + if kv.debug == 1 + disp(' Applying Butterworth low pass ') + disp(strcat(' Polynomial order of Butterworth filter: ',num2str(kv.butterpoly))) + disp(strcat(' Cut-off frequency is: ',num2str(kv.upper_cutfreq),' Hz')) + end + % if isoctave; pkg load signal; end + if exist('OCTAVE_VERSION','builtin') ~= 0; pkg load signal; end + cut_off_freq_norm = kv.upper_cutfreq/(fs/2); + + [lp_a,lp_b] = butter(kv.butterpoly,cut_off_freq_norm); + f_ir = zeros(pos,ear,Ns); + for ii=1:pos + for jj=1:ear + sir = squeeze( IR(ii,jj,:) ); + f_sir = filter(lp_a,lp_b,sir); + f_ir(ii,jj,:) = f_sir; + end + end + +else + if kv.debug == 1; disp(' No low pass filter is applied'); end + f_ir = IR; +end + +% ---------------------- estimating itd ------------------------------- +% --------------------------------------------------------------------- + +% ---------------------- Threshold ------------------------------------ +switch(flags.mode) + case 'Threshold' + if kv.debug == 1 + disp(' Threshold mode') + disp(strcat(' Threshold level is: ',num2str(kv.threshlvl),'dB')) + end + + if flags.do_fp + for ii=1:pos + for jj=1:ear + indB = 0.5*mag2db(squeeze(f_ir(ii,jj,:)).^2); + [~,B] = findpeaks(indB); + th_value = indB(B(1)) + kv.threshlvl; + toa(ii,jj) = find(indB>th_value,1); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + else + for ii=1:pos + for jj=1:ear + indB = 0.5*mag2db(squeeze(f_ir(ii,jj,:)).^2); + th_value = max(indB) + kv.threshlvl; + toa(ii,jj) = find(indB>th_value,1); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + end + + +% ---------------------- Cross-Correlation ---------------------------- + case 'Cen_e2' + if kv.debug == 1; disp(' Cen-e2 mode'); end + for ii=1:pos + for jj = 1:ear + e_sir_sq = abs(hilbert(squeeze(f_ir(ii,jj,:))).^2); + toa(ii,jj) = centroid(transpose(1:Ns),e_sir_sq); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + + case 'MaxIACCr' + if kv.debug == 1; disp(' MaxIACCr mode'); end + for ii=1:pos + cc = xcorr(squeeze(f_ir(ii,1,:)),squeeze(f_ir(ii,2,:))); + [IACC(ii),idx_lag] = max(abs(cc)); + toa_diff(ii) = idx_lag - Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + case 'MaxIACCe' + if kv.debug == 1; disp(' MaxIACCe mode'); end + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2); + [IACC(ii),idx_lag] = max(abs(cc)); + toa_diff(ii) = idx_lag - Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACCr' + if kv.debug == 1; disp(' CenIACCr mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + cc = xcorr(squeeze(f_ir(ii,1,:)),squeeze(f_ir(ii,2,:))); + pos_cc = abs(cc); + IACC(ii) = max(pos_cc); + toa_diff(ii) = centroid(x,pos_cc)-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACCe' + if kv.debug == 1; disp(' CenIACCe mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2); + IACC(ii) = max(abs(cc)); + toa_diff(ii) = centroid(x,abs(cc))-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'CenIACC2e' + if kv.debug == 1; disp(' CenIACC2e mode'); end + x = transpose(1:(Ns*2-1)); + for ii=1:pos + e_sir1 = abs(hilbert(squeeze(f_ir(ii,1,:)))); + e_sir2 = abs(hilbert(squeeze(f_ir(ii,2,:)))); + cc = xcorr(e_sir1,e_sir2).^2; + IACC(ii) = max(abs(cc)); + toa_diff(ii) = centroid(x,abs(cc))-Ns; + end + if flags.do_guesstoa + toa = guesstoa(toa_diff,toa, kv.avgtoa); + end + + + case 'PhminXcor' + if kv.debug == 1; disp(' PhminXcor mode'); end + ir_min=ARI_MinimalPhase(Obj); + for ii=1:pos + for jj=1:ear + cc = xcorr(squeeze(IR(ii,jj,:)),squeeze(ir_min(ii,jj,:))); + [~,toa(ii,jj)] = max(abs(cc)); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end + + +% ---------------------- Groupdelay ----------------------------------- + case 'IRGD' + if kv.debug == 1; disp(' IRGD mode'); end + for ii = 1:pos + for jj = 1:ear + f_sir = squeeze( f_ir(ii,jj,:) ); + [gd,w] = grpdelay(transpose(double(f_sir)),1,Ns,fs); + toa(ii,jj)=mean(gd(find(w>kv.lower_cutfreq): ... + find(w>kv.upper_cutfreq))); + end + toa_diff(ii) = toa(ii,1) - toa(ii,2); + end +end +toa_diff = toa_diff/fs; +toa = toa/fs; + +% Calculate Delay, add to Obj +for k = 1:size(IR, 1) + % Get onset + OnSetL = IR_start(IR(k,1,:), kv.thr); % L + OnSetR = IR_start(IR(k,2,:), kv.thr); % R + % Onset difference + delay(k,:) = [OnSetL, OnSetR]; +end + +Obj = SOFAaddVariable(Obj,'Data.Delay','MR',delay); + + + +% ------------------------------------------------------------------------- +% ---------------------- Functions ---------------------------------------- +% ------------------------------------------------------------------------- + + +% ---------------------- Centroid ----------------------------------------- +function idx_cent = centroid(x,y) +idx_cent = sum(x.*y)/sum(y); + +% ---------------------- guess toa ---------------------------------------- +function toa = guesstoa(toa_diff,toa, avgtoa) +toa(:,1) = toa(:,1) + avgtoa + toa_diff/2; +toa(:,2) = toa(:,2) + avgtoa - toa_diff/2; + +% ---------------------- Create minimal phase ----------------------------- +% as used in ziegelwanger2014 +function hMmin=ARI_MinimalPhase(Obj) +hM=Obj.Data.IR; +hMmin=hM; + +for jj=1:Obj.API.R + for ii=1:Obj.API.M + h=squeeze(hM(ii,jj,:)); + + amp1=abs(fft(h)); + amp2=amp1; + + an2u=-imag(hilbert(log(amp1))); + an2u=an2u(1:floor(length(h)/2)+1); + + an3u=[an2u; -flipud(an2u(2:end+mod(length(h),2)-1))]; + an3=an3u-round(an3u/2/pi)*2*pi; + + amp2=amp2(1:floor(length(h)/2)+1); + amp3=[amp2; flipud(amp2(2:end+mod(length(h),2)-1))]; + + h2=real(ifft(amp3.*exp(1i*an3))); + hMmin(ii,jj,:)=h2(1:Obj.API.N); + end +end + +% -------------------------- sampleStart ---------------------------------- +function sampleStart = IR_start(IR,threshold) +% 20210207 - Davi Carvalho, adapted from ita_start_IR.m from https://git.rwth-aachen.de/ita/toolbox/-/blob/master/kernel/DSP/ita_start_IR.m +threshold = -abs(threshold); +IR_square = IR.^2; +% Max value on IR +[pk_val, idx_max] = max(IR_square(:)); +abs_dat = 10.*log10(IR_square(1:idx_max)) - 10.*log10(pk_val); + +lastBelowThreshold = find(abs_dat < threshold,1,'last'); +if ~isempty(lastBelowThreshold) + sampleStart = lastBelowThreshold; +else + sampleStart = 1; +end +% Check if oscillations exist before the last value below threshold +% If so, these are part of the RIR and need to be considered. +idx6dBaboveThreshold = find(abs_dat(1:sampleStart) > threshold + 6); +if ~isempty(idx6dBaboveThreshold) + tmp = find(abs_dat(1:idx6dBaboveThreshold(1)) < threshold, 1 ,'last'); + if isempty(tmp) % without this if, the function would generate an error, if the oscillation persists until the first sample + sampleStart = 1; + else + sampleStart = tmp; + end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m new file mode 100644 index 0000000000000000000000000000000000000000..e56b3964a14a193a78db1f7ac97f132cecc1e98b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcalculateLFE.m @@ -0,0 +1,111 @@ +function Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax) +% Low frequency extention +% +% function Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax) +% +% Description: +% This function extrapolates low frequency content of +% SOFA SimpleFreeFieldHRIR objects by considering a +% linear behavior to the low frequency content + +% Usage: Obj = SOFAcalculateLFE(Obj, fmin, fmax) +% +% Input parameters: +% Obj: SOFA object with SimpleFreeFieldHRIR convention. +% fmin: Minimal frequency to be calculated (default: 15Hz) +% fmax: Reference frequency value to be extended until fmin +% (default: 500Hz) +% +% Output arguments: +% Obj: SOFA object with SimpleFreeFieldHRIR convention. + + +% #Author: Davi R. Carvalho, UFSM - Acoustical Engineering (07.04.2021) +% #Author: Michael Mihocic: adapted for SOFA 2.0 release; header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcalculateLFE +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% parse inputs +if nargin < 3 + fmax = 500; % max linear frequency +end +if nargin < 2 + fmin = 15; % minimum freq +end + +%% Preprocess +fs = Obj.Data.SamplingRate; +IR = shiftdim(Obj.Data.IR, 2); +N = size(IR, 1); +freq_vec = (0:N/2-1)*fs/N; + +% Check if defined fmax data exists in raw hrir +if length(find(fmax > freq_vec)) == 1 + fmax = freq_vec(3); +end + + +% Minimum length necessary to contain fmin +N_ext = ceil(fs/fmin); +if N_ext <= N + N_ext = N; + freq_vec_ext = freq_vec; +else + freq_vec_ext = (0:N_ext/2-1)*fs/N_ext; +end +f500Hz = dsearchn(freq_vec_ext.', fmax); % idx at defined linear part of HRTFs + +[~, ~, ~, Obj] = SOFAcalculateITD(Obj, 'samples', 'debug', 1); +% [~, ObjD] = SOFAcalculateITDdavi(Obj, 'samples'); + +%% extrap low frequency +ir_interp = zeros(size(IR, 2), size(IR, 3), N_ext); +for k = 1:size(IR, 2) + for l = 1:size(IR, 3) + time = [IR(:,k,l); zeros(ceil(N_ext - N), 1)]; + mag = mag2db(abs(fft(time))); + mag_interp = mag; + + % interp + x = [freq_vec_ext(2), freq_vec_ext(f500Hz)]; + xq = freq_vec_ext(2:f500Hz); + y_mag = [mag(f500Hz); mag(f500Hz)]; + if exist('OCTAVE_VERSION','builtin') + mag_interp(2:f500Hz) = interp1(x, y_mag, xq); + else + mag_interp(2:f500Hz) = interp1(x, y_mag, xq, 'makima'); + end + + mag_interp = 10.^(mag_interp./20); + H = mag_interp(1:round(N_ext/2)); + + % back to time domain + ir_interp(k,l,:) = circshift(real(ifft(get_min_phase(abs(H)))), Obj.Data.Delay(k,l)); + end +end + + +%% OUTPUT +Obj_lfe = Obj; +% ir_interp = ir_interp./max(abs(ir_interp(:))) .* max(abs(IR(:))); +Obj_lfe.Data.IR = ir_interp; +end + + +function Hmin = get_min_phase(H, varargin) +% Calculate minimum-phase spectrum from magnitude via the Hilbert Transform +%% Preprocess +H = [H; flip(H)]; % back to double sided spectrum + +%% Get minimum_phase +phi_min = imag(hilbert(-(log(abs(H)+eps)))); % eps makes avoids log(0) = -inf +% Filtro inverso complexo (cria fase) +Hmin = abs(H).*exp(1i*(phi_min)); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m new file mode 100644 index 0000000000000000000000000000000000000000..cbf03103a4ae032e8078a9916fddb18a94f863a8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcheckFilename.m @@ -0,0 +1,30 @@ +function newfn=SOFAcheckFilename(fn) +%SOFACHECKFILENAME +% newFN = SOFAcheckFilename(FN) checks the filename FN replaces certain characters + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcheckFilename +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% filename = string? +if ~ischar(fn) + error('Filename must be a string.'); +end +if strcmp(fn(1:7),'http://') + newfn=fn; % remote file +else + fn=strrep(fn,'/',filesep); + fn=strrep(fn,'\',filesep); + if length(fn)>4 + if strcmpi(fn(1:4),['db:' filesep]), fn=[SOFAdbPath fn(5:end)]; end + end + newfn=fn; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..c055c62533f41e7a6950b9d4de2b2d4cddf64f08 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompact.m @@ -0,0 +1,93 @@ +function [Obj, log] = SOFAcompact(Obj) +%SOFAcompact +% Obj = SOFAcompact(Obj) +% compacts the unique value to singleton dimensions +% of variables where possible. +% Current limitation: Variables with 3 dimensions will be only compacted +% when the third dimension is the compressible one. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) + +% SOFA Toolbox - function SOFAcompact +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "Licence") +% You may not use this work except in compliance with the Licence. +% You may obtain a copy of the Licence at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the Licence is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the Licence for the specific language governing permissions and limitations under the Licence. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); +dims=SOFAdefinitions('dimensions'); + +%% compact w/o data +X=rmfield(Obj,{'Data','API'}); +Xf=fieldnames(X); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % get all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.(Xf{ii}),'rows'); else n=unique(Obj.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.(Xf{ii})=n; else Obj.(Xf{ii})=n'; end; % compressed! + case 3 + d=cell2mat(strfind(dims,'I')); + switch d + case 3 + y=unique(reshape(Obj.(Xf{ii}),[],size(Obj.(Xf{ii}),d))','rows'); + if size(y,1)>1, continue; end; % entries not unique --> not compressible + Obj.(Xf{ii})=reshape(y',size(Obj.(Xf{ii}),1),size(Obj.(Xf{ii}),2)); + otherwise + warning('SOFA:compact',[Xf{ii} ' not compressed (currently limited)']); + end + end +end + +%% Compact the data +Xf=fieldnames(Obj.Data); +for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not compressible + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not compressible + dims=OC.API.Dimensions.Data.(Xf{ii}); % get all possible dimensions + if ~iscell(dims), continue; end; % variable with a single dimension definition --> not compressible + if numel(dims)==1, continue; end; % variable with a single dimension definition --> not compressible + switch length(dims{1}) % how many dimensions do we have? + case 1 + n=unique(Obj.Data.(Xf{ii})); + if length(n)>1, continue; end; % entries not unique --> not compressible + Obj.Data.(Xf{ii})=n; % compressed! + case 2 + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + if strcmp(dims{d}(1),'I'), n=unique(Obj.Data.(Xf{ii}),'rows'); else n=unique(Obj.Data.(Xf{ii})','rows')'; end; + if size(n,1)>1, continue; end; % entries not unique --> not compressible + if strcmp(dims{d}(1),'I'), Obj.Data.(Xf{ii})=n; else Obj.Data.(Xf{ii})=n'; end; % compressed! + case 3 + % missing + warning('SOFA:compact',['Data.' Xf{ii} ' not compressed (functionality limited)']); + end +end + +%% clean up +Obj=SOFAupdateDimensions(Obj); +if length(log)>1, log=log(2:end); else log={}; end; + +function vec=getdim(Obj,str) +vec=NaN(1,length(str)); +for ii=1:length(str) + vec(ii)=Obj.(upper(str(ii))); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m new file mode 100644 index 0000000000000000000000000000000000000000..f703e3f1318172591967cb13856444be985abe96 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompare.m @@ -0,0 +1,58 @@ +function [tf,reason,where] = SOFAcompare(Obj1, Obj2, varargin) +%SOFAcompare +% TF = SOFAcompare(A, B) compares A and B and +% returns logical 1 (true) if they are identical. +% +% [TF,REASON,WHERE] = SOFAcompare(A, B) provides the REASON +% and shows WHERE the difference arose. +% +% ... = SOFAcompare(A, B, 'ignoreDate') ignores the global attributes +% DateCreated and DateModified. +% +% +% Limited functionality!!! Only attributes are compared now. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (20.10.2021) +% +% SOFA Toolbox - function SOFAcompare +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.flags.type={'all','ignoreDate'}; +[flags,~]=SOFAarghelper({},definput,varargin); + + +tf=1; +reason=''; +where=''; + +% % check if the size is equal +% o1=whos('Obj1'); +% o2=whos('Obj2'); +% if o1.bytes ~= o2.bytes, tf=0; reason='Different size'; return; end + + % get the field names +Xf=fieldnames(Obj1); + + % ignore DateCreated and DateModified? +if flags.do_ignoreDate + Xf=fieldnames(rmfield(Obj1,{'GLOBAL_DateCreated','GLOBAL_DateModified'})); +end + + % check if we have the same fields in Obj2 as in Obj1 +for ii=1:length(Xf) + if ~isfield(Obj2,Xf{ii}), tf=0; reason='Field missing in B'; where=Xf{ii}; return; end +end + + % check if we have the same content of attributes in Obj2 as in Obj1 +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), continue; end + if ~strcmp(Obj1.(Xf{ii}),Obj2.(Xf{ii})), tf=0; reason='Field not equal'; where=Xf{ii}; return; end +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..d1919ecf97105fd41955d27d2bd6238551f4e422 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAcompileConventions.m @@ -0,0 +1,209 @@ +function [dispOutput] = SOFAcompileConventions(conventions) +%SOFAcompileConventions +% +% [dispOutput] = SOFAcompileConventions(sofaconventions) compiles the specified +% SOFA conventions. For every convention, a CSV file must exist that +% will be compiled to a .mat file and used later by SOFAgetConventions(). +% +% The CSV file must be in the directory conventions and can contain +% files for multiple versions of the same conventions. For each version, +% SOFAcompileConventions generates 3 files, one for each flag (r, m, and all) +% +% Before compiling, SOFAcompileConventions checks if the modification +% date of the .mat files is older than that of the .csv file. Compiling +% is not performed if all .mat files are newer than the .csv file. This +% behaviour is required for operation in a read-only directory. +% +% SOFAcompileConventions ignores all files beginning with '_' (underscore). +% +% Output variable dispOutput contains a string with all compiled +% conventions information. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (20.10.2021) +% #Author: Michael Mihocic: display information changed to output variable (11.11.2021) +% +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +baseFolder = fileparts(which('SOFAstart')); +dispOutput=''; + +if nargin<1 + conventionFiles = dir(fullfile(baseFolder,'conventions','*.csv')); + conventions={}; + for file = conventionFiles' + [~,name,~] = fileparts(file.name); + if name(1)=='_', continue; end + % Check if mat files exist for every convention flag (r,m,a) + flagsCounter = 0; + for flag = 'rma' + flagFile = dir(fullfile(baseFolder,'conventions', ... + strcat(name,'_',flag,'_*.mat'))); + if ~isempty(flagFile) && flagFile(1).datenum>file.datenum + flagsCounter = flagsCounter+1; + end + end + % If not all three files are up to request conventions compilation + if flagsCounter~=3 + conventions{end+1} = name; + end + end +elseif ~iscell(conventions) + conventions={conventions}; +end + + +%% ----- Convert convention csv files into mat files ----- +for convention = conventions + % Read convention description from csv file + fid = fopen(fullfile(baseFolder,'conventions', ... + strcat(convention{:},'.csv'))); + if exist('OCTAVE_VERSION','builtin') + % We're in Octave where textscan works differently since ver. 4.2 + C_lines = textscan(fid,'%s','Delimiter','\n','Headerlines',1); + C_line = C_lines{1}{1}; + C_elems = cell(length(C_lines{1}),1); + C_maxcols = 2; + for line_nr = 1:length(C_lines{1}) + C_line = C_lines{1}{line_nr}; + C_elems{line_nr} = strsplit(C_line, '\t', 'collapsedelimiters', false); + C_maxcols = max(C_maxcols, length(C_elems{line_nr})); + end + % C = cell(1,length(C_elems{1})); + C = cell(1,C_maxcols); + for col_nr = 1:C_maxcols + % for col_nr = 1:length(C_elems{1}) + C{col_nr} = cell(length(C_lines{1}),1); + end + for line_nr = 1:length(C_lines{1}) + for col_nr = 1:length(C_elems{line_nr}) + % for col_nr = 1:length(C_elems{1}) + C{col_nr}{line_nr} = C_elems{line_nr}{col_nr}; + end + end + else + x=char(fread(fid)); + xr=strrep(x',char([9 13 10]),char([9 32 32 13 10])); + C = textscan(xr,'%s%s%s%s%s%s','Delimiter','\t','Headerlines',1,'WhiteSpace',''); + end + fclose(fid); + + % Convert to mat files for r,m,a cases + for flag = 'rma' + % Convert to SOFA object + Obj = compileConvention(C,flag); + % Write to mat file +% if strcmp(Obj.GLOBAL_SOFAConventions,convention{:}) + if strcmp(flag,'r') % && dispOutput==1 % Display message only the very first time +% disp(['Compiling ',convention{:},'.csv: ', ... +% Obj.GLOBAL_SOFAConventions, ' ', ... +% Obj.GLOBAL_SOFAConventionsVersion]); + if ~strcmp(dispOutput,''); dispOutput = [dispOutput 10]; end + dispOutput = [dispOutput 'Compiling ',convention{:},'.csv: ', Obj.GLOBAL_SOFAConventions, ' ', Obj.GLOBAL_SOFAConventionsVersion]; + end + save(fullfile(baseFolder,'conventions', ... + strcat(Obj.GLOBAL_SOFAConventions,'_',flag,'_', Obj.GLOBAL_SOFAConventionsVersion,'.mat')), ... + 'Obj','-v7'); +% else +% warning([convention{:} '.csv: file name not convention name (' Obj.GLOBAL_SOFAConventions]); +% end + end +end +end % of main function + + +%% ----- Subroutines ----------------------------------------------------- +function Obj = compileConvention(convention,flag) + % Compile convention mat structure for the specified flag + % + % The csv files provide the following columns (corresponding cell numbers in + % brackets) + % Name {1}, Default {2}, Flags {3}, Dimensions {4}, Type {5}, Comment {6} + convName = convention{1}; + convDefault = convention{2}; + convFlags = convention{3}; + convDimensions = convention{4}; + convType = convention{5}; + convComment = convention{6}; + + % Create object structure + for ii=1:length(convName) + % Append 'a' to Flags entry as it only contains 'm' or 'r' in the csv file + convFlags{ii} = strcat(convFlags{ii},'a'); + if ~isempty(regexp(convFlags{ii},flag, 'once')) + var = regexprep(convName{ii},':','_'); + switch lower(convType{ii}) + case 'double' + % Convert default to double + convDefault{ii} = str2num(convDefault{ii}); + case 'string' + eval(['convDefault{ii}=' convDefault{ii} ';']); + end + if isempty(strfind(var,'Data.')) + Obj.(var) = convDefault{ii}; + if isempty(strfind(var,'_')) % && ~sum(strcmp(var,dims)) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quotations and insert line breaks + Obj.API.Dimensions.(var)=eval(['{''' y '''}']); + end + else + Obj.Data.(var(6:end)) = convDefault{ii}; + if isempty(strfind(var(6:end),'_')) + x2 = regexprep(convDimensions{ii},' ',''); % remove spaces + y = regexprep(x2,',',['''' 10 '''']); % enclose in quatations and insert line breaks + Obj.API.Dimensions.Data.(var(6:end))=eval(['{''' y '''}']); + end + end + end + end + + + % ----- Overwrite some special fields ----- + if isfield(Obj,'GLOBAL_APIVersion') + Obj.GLOBAL_APIVersion = SOFAgetVersion; + end + if isfield(Obj,'GLOBAL_APIName') + Obj.GLOBAL_APIName = 'ARI Matlab/Octave API'; + end + + % ----- Create dimension size variables - if not read-only ----- + if strcmp(flag,'r') + return; + else + % Fix dimension sizes (why we have to fix them?) + Obj.API.I = 1; + Obj.API.C = 3; + % Variable-dependent dimension sizes + dims = 'renm'; + % Check all metadata variables + fields =fieldnames(rmfield(Obj.API.Dimensions,'Data')); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(fields{jj}),dim(1)); + break; + end + end + end + % Check all data variables + fields = fieldnames(Obj.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fields) + dim = strfind(Obj.API.Dimensions.Data.(fields{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fields{jj}),dim(1)); + break; + end + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..577719ebb84f7a8e5f299e8c3de1404d1a07562d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertConventions.m @@ -0,0 +1,461 @@ +function Obj=SOFAconvertConventions(Obj,varargin) +% Obj = SOFAconvertConventions(Obj) converts a SOFA object to SimpleFreeFieldHRIR +% +% Supported conventions: +% SimpleFreeFieldSOS +% SimpleFreeFieldTF +% SimpleFreeFieldHRTF +% FreeFieldHRTF +% some special cases of GeneralTF, GeneralTF-E. +% +% When using optional input values, they are transferred to and must be supported by SOFAarghelper function: +% Obj=SOFAconvertConventions(Obj,varargin) +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% get convention to be converted +if ~isempty(varargin) + definput.flags.convention=SOFAgetConventions(); + definput.flags.convention=strrep(definput.flags.convention,'-','_'); + + if contains(varargin,'-') + varargin=strrep(varargin,'-','_'); + end + [flags,~]=SOFAarghelper({},definput,varargin); + + newConvention = flags.convention; + if contains(newConvention,'_') + newConvention=strrep(newConvention,'_','-'); + end + % check if given convention is available + if isempty( SOFAgetConventions(newConvention)) + error([newConvention, ' not a valid convention.']) + end +else + newConvention = 'SimpleFreeFieldHRIR'; +end +oldConvention = Obj.GLOBAL_SOFAConventions; +%% no conversion needed if convention is the same +if(strcmp(oldConvention,newConvention)) +% warning(['No conversion done, as Obj already conforms to ', newConvention,'.']) + return +end + +%% convert Object +newObj = SOFAgetConventions(newConvention); +oldObj = SOFAgetConventions(oldConvention); + +Obj.GLOBAL_SOFAConventions=newObj.GLOBAL_SOFAConventions; +Obj.GLOBAL_SOFAConventionsVersion=newObj.GLOBAL_SOFAConventionsVersion; +Obj.GLOBAL_Conventions = newObj.GLOBAL_Conventions; +% convert Data +try + switch Obj.GLOBAL_DataType + case 'SOS' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + Obj.Data.IR(ii,jj,:)=sosfilt(reshape(squeeze(Obj.Data.SOS(ii,jj,:)),6,[])',impulse); + end + end + Obj.Data=rmfield(Obj.Data,'SOS'); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Data.SOS = Obj.Data.SOS; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + IR=sosfilt(reshape(squeeze(Data.SOS(ii,jj,:)),6,[])',impulse); + TF=fft(IR,Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + N=512; + impulse=[1; zeros(N-1,1)]; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.SOS; + Data.SOS = Obj.Data.SOS; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + IR=sosfilt(reshape(squeeze(Data.SOS(ii,jj,:)),6,[])',impulse); + TF=fft(IR,Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,'SOS'); + Obj=SOFAupdateDimensions(Obj); + + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + + case 'TF' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + if sum(diff(diff(Obj.N))) + fs=max(Obj.N)*2; % irregular grid, find the smallest frequency difference + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + Nidx=Obj.N*N/fs+1; + Nsize=floor(N/2+1); + else + N=2*(length(Obj.N)-1); % regular grid (from an DFT probably), works for odd length only + fs=max(Obj.N)*2; + Nidx=1:length(Obj.N); + Nsize=length(Obj.N); + end + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=fs; + Obj.Data.SamplingRate_Units='hertz'; + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(Nsize,1); + s(Nidx)=squeeze(Obj.Data.Real(ii,jj,:))+1i*squeeze(Obj.Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); + end + Obj.Data.Delay=zeros(1,Obj.API.R); + Obj.SourcePosition_Type=newObj.SourcePosition_Type; + Obj.SourcePosition_Units=newObj.SourcePosition_Units; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag'}); + if isfield(Obj.API.Dimensions,'Data') + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + end + elseif strcmp(newObj.GLOBAL_DataType,'TF') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType = newObj.GLOBAL_DataType; + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + + + case 'TF-E' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + Obj.API.Dimensions.Data.IR=Obj.API.Dimensions.Data.Real; + Obj.Data.SamplingRate=max(Obj.N)*2; + Obj.Data.SamplingRate_Units='hertz'; + % convert sperical harmonics + if strcmpi(Obj.EmitterPosition_Type,'spherical harmonics') + [X,Y,Z]=sphere(60); + [azi_rad,ele_rad,radius]=cart2sph(X,Y,Z); + azi=azi_rad/pi*180; + ele=ele_rad/pi*180; + [azi,ele]=nav2sph(azi,ele); + radius=1.2*radius; + azi=azi(:); + ele=ele(:); + radius=radius(:); + + S = sph2SH([azi ele], sqrt(Obj.API.E)-1); + Obj.API.M=size(S,1); + Obj.SourcePosition=[azi ele radius]; + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degrees,degrees,metre'; + + Data.Real = zeros(Obj.API.M,2,Obj.API.N); + Data.Imag = zeros(Obj.API.M,2,Obj.API.N); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Data.Real(:,ii,jj)=S*squeeze(Obj.Data.Real(1,ii,jj,:)); + Data.Imag(:,ii,jj)=S*squeeze(Obj.Data.Imag(1,ii,jj,:)); + end + end + else +% Obj.EmitterPosition=Obj.SourcePosition; +% Obj.EmitterPosition_Type=Obj.SourcePosition_Type; +% Obj.EmitterPosition_Units=Obj.SourcePosition_Units; +% Data.Real = shiftdim(squeeze(Obj.Data.Real(1,:,:,:)),2); +% Data.Imag = shiftdim(squeeze(Obj.Data.Imag(1,:,:,:)),2); +% Obj.API.M=Obj.API.E; + error(['Converting ' Obj.GLOBAL_SOFAConventions ' to ' newObj.GLOBAL_SOFAConventions ' not supported yet']); + end + + if sum(diff(diff(Obj.N))) + fs=max(Obj.N)*2; % irregular grid, find the smallest frequency difference + N=fs/min([min(diff(Obj.N)) Obj.N(1)]); + N=2*(round(N/2+1)-1); + Nidx=Obj.N*N/fs+1; + Nsize=floor(N/2+1); + else + N=2*(length(Obj.N)-1); % regular grid (from an DFT probably), works for odd length only + fs=max(Obj.N)*2; + Nidx=1:length(Obj.N); + Nsize=length(Obj.N); + end + + Obj.Data.IR=zeros(Obj.API.M, Obj.API.R, N); + for ii=1:Obj.API.M + for jj=1:Obj.API.R + s=zeros(Nsize,1); + s(Nidx)=squeeze(Data.Real(ii,jj,:))+1i*squeeze(Data.Imag(ii,jj,:)); + Obj.Data.IR(ii,jj,:)=myifftreal(s,N); + end + Obj.SourcePosition(ii,:)=SOFAconvertCoordinates(Obj.SourcePosition(ii,:),Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); + end + Obj.Data.Delay=zeros(Obj.API.M,Obj.API.R,1); + Obj.Data.SamplingRate=fs; + Obj=rmfield(Obj,{'N','N_LongName','N_Units'}); + Obj.Data=rmfield(Obj.Data,{'Real','Imag'}); + Obj.API.Dimensions.Data=rmfield(Obj.API.Dimensions.Data,{'Real','Imag'}); + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + % convert sperical harmonics + if strcmpi(Obj.EmitterPosition_Type,'harmonics') + [X,Y,Z]=sphere(60); + [azi_rad,ele_rad,radius]=cart2sph(X,Y,Z); + azi=azi_rad/pi*180; + ele=ele_rad/pi*180; + [azi,ele]=nav2sph(azi,ele); + radius=1.2*radius; + azi=azi(:); + ele=ele(:); + radius=radius(:); + + S = sph2SH([azi ele], sqrt(Obj.API.E)-1); + Obj.API.M=size(S,1); + Obj.SourcePosition=radius; + Obj.SourcePosition_Type='spherical harmonics'; + Obj.SourcePosition_Units='metre'; + + oldObj.Data.Real = Obj.Data.Real; + oldObj.Data.Imag = Obj.Data.Imag; + Obj.Data.Real = zeros(Obj.API.M,2,Obj.API.N); + Obj.Data.Imag = zeros(Obj.API.M,2,Obj.API.N); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(:,ii,jj)=S*squeeze(oldObj.Data.Real(1,ii,jj,:)); + Obj.Data.Imag(:,ii,jj)=S*squeeze(oldObj.Data.Imag(1,ii,jj,:)); + end + end + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; + else + error('Conventions not supported'); + end + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + % no data conversion needed + end + + case 'FIR' + if strcmp(newObj.GLOBAL_DataType,'SOS') + % TODO + error('Not supported yet') + elseif strcmp(newObj.GLOBAL_DataType,'FIR') + % no data conversion needed + elseif strcmp(newObj.GLOBAL_DataType,'TF') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + IR=Obj.Data.IR; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + TF=fft(IR(ii,jj,:),Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + elseif strcmp(newObj.GLOBAL_DataType,'TF-E') + Obj.GLOBAL_DataType=newObj.GLOBAL_DataType; + IR=Obj.Data.IR; + fs=Obj.Data.SamplingRate; + Obj=rmfield(Obj,{'Data'}); + Obj.N=linspace(0,fs/2,Obj.API.N/2+1)'; + Obj.Data.Real = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.Data.Imag = zeros(Obj.API.M,Obj.API.R,length(Obj.N)); + Obj.N_LongName='frequency'; + Obj.N_Units='hertz'; + for ii=1:Obj.API.M + for jj=1:Obj.API.R + TF=fft(IR(ii,jj,:),Obj.API.N); + TF=TF(:,:,1:length(Obj.N)); + Obj.Data.Real(ii,jj,:)=real(TF); + Obj.Data.Imag(ii,jj,:)=imag(TF); + end + end + Obj=SOFAupdateDimensions(Obj); + + Obj.API.E=Obj.API.M; + Obj.API.M=1; + realBuffer=shiftdim(Obj.Data.Real,1); + Obj.Data.Real=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Real(1,:,:,:)=realBuffer;% MRN --> 1RNM --> MRNE with M=1 + Obj.API.Dimensions.Data.Real='MRNE'; + imagBuffer=shiftdim(Obj.Data.Imag,1); + Obj.Data.Imag=zeros(1,Obj.API.R,Obj.API.N,Obj.API.E); + Obj.Data.Imag(1,:,:,:)=imagBuffer; + Obj.API.Dimensions.Data.Imag='MRNE'; + Obj.EmitterPosition=Obj.SourcePosition; + Obj.API.Dimensions.EmitterPosition='ECI'; + Obj.SourcePosition=[0 0 0]; + Obj.API.Dimensions.SourcePosition='IC'; + Data.Real=Obj.Data.Real; + Data.Imag=Obj.Data.Imag; + L=40; % actual SH order + [S, Obj.API.E]=sph2SH(Obj.EmitterPosition(:,1:2), L); + + Sinv=pinv(S); + Obj.Data.Real=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + Obj.Data.Imag=zeros(1, Obj.API.R, Obj.API.N, Obj.API.E); + for ii=1:Obj.API.R + for jj=1:Obj.API.N + Obj.Data.Real(1,ii,jj,:)=Sinv*squeeze(Data.Real(1,ii,jj,:)); + Obj.Data.Imag(1,ii,jj,:)=Sinv*squeeze(Data.Imag(1,ii,jj,:)); + end + end + + Obj.EmitterPosition=mean(Obj.EmitterPosition(:,3)); + Obj.EmitterPosition_Type='Spherical Harmonics'; + Obj.EmitterPosition_Units='Metre'; + end + otherwise + error(['Turning ',oldConvention,' into ',... + newObj.GLOBAL_SOFAConventions,' not supported.']); + end +catch ME + rethrow(ME); + error(['Turning ',oldConvention,' into ',... + newObj.GLOBAL_SOFAConventions,' not supported.']); +end +Obj.SourcePosition=SOFAconvertCoordinates(Obj.SourcePosition,Obj.SourcePosition_Type,newObj.SourcePosition_Type,Obj.SourcePosition_Units,newObj.SourcePosition_Units); +Obj.SourcePosition_Type=newObj.SourcePosition_Type; +Obj.SourcePosition_Units=newObj.SourcePosition_Units; +if strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics') && ~strcmpi(newObj.EmitterPosition_Type,'Spherical Harmonics') + Obj.EmitterPosition=[0 0 0]; + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; +elseif ~strcmpi(newObj.EmitterPosition_Type,'Spherical Harmonics') + Obj.EmitterPosition=SOFAconvertCoordinates(Obj.EmitterPosition,Obj.EmitterPosition_Type,newObj.EmitterPosition_Type,Obj.EmitterPosition_Units,newObj.EmitterPosition_Units); + Obj.EmitterPosition_Type=newObj.EmitterPosition_Type; + Obj.EmitterPosition_Units=newObj.EmitterPosition_Units; +end +Obj.ListenerPosition=SOFAconvertCoordinates(Obj.ListenerPosition,Obj.ListenerPosition_Type,newObj.ListenerPosition_Type,Obj.ListenerPosition_Units,newObj.ListenerPosition_Units); +Obj.ListenerPosition_Type=newObj.ListenerPosition_Type; +Obj.ListenerPosition_Units=newObj.ListenerPosition_Units; +Obj.ReceiverPosition=SOFAconvertCoordinates(Obj.ReceiverPosition,Obj.ReceiverPosition_Type,newObj.ReceiverPosition_Type,Obj.ReceiverPosition_Units,newObj.ReceiverPosition_Units); +Obj.ReceiverPosition_Type=newObj.ReceiverPosition_Type; +Obj.ReceiverPosition_Units=newObj.ReceiverPosition_Units; +Obj=SOFAupdateDimensions(Obj); + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m new file mode 100644 index 0000000000000000000000000000000000000000..50b4f392c3e5971f5efc632389a978dee6cd7bc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAconvertCoordinates.m @@ -0,0 +1,66 @@ + function output = SOFAconvertCoordinates(input,input_type,output_type,~,~) +%SOFAconvertCoordinates +% output = SOFAconvertCoordinates(input,input_type,output_type), converts the specified coordinate variable to specified +% output_type and returns the results. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: type horizontal-polar removed (not defined in SOFA) (08.03.2021) +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAconvertCoordinates +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% check input +if strcmp(input_type,'cartesian')==0 && ... + strcmp(input_type,'spherical')==0 && ... + strcmp(input_type,'geodesic')==0 % && ... +% strcmp(input_type,'horizontal-polar')==0 + error('Specified "input_type" is not supported'); +end +if strcmp(output_type,'cartesian')==0 && ... + strcmp(output_type,'spherical')==0 && ... + strcmp(output_type,'geodesic')==0 % && ... +% strcmp(output_type,'horizontal-polar')==0 + error('Specified "output_type" is not supported'); +end + +output=input; +%% convert coordinates if necessary +if strcmp(output_type,input_type)==0 + temp=input; + switch input_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [temp(:,1),temp(:,2),temp(:,3)]=sph2cart(deg2rad(input(:,1)),deg2rad(input(:,2)),input(:,3)); +% case 'horizontal-polar' +% [temp(:,1),temp(:,3),temp(:,2)]=sph2cart(deg2rad(input(:,2)),deg2rad(input(:,1)),input(:,3)); +% temp(:,2)=-temp(:,2); + end + + output=temp; + switch output_type + case 'cartesian' + %do nothing + case {'spherical','geodesic'} + [output(:,1),output(:,2),output(:,3)]=cart2sph(temp(:,1),temp(:,2),temp(:,3)); + output(:,1:2)=rad2deg(output(:,1:2)); +% case 'horizontal-polar' +% % [output(:,2),output(:,1),output(:,3)]=cart2sph(temp(:,1),temp(:,3),-temp(:,2)); +% % output(:,1:2)=rad2deg(output(:,1:2)); +% % output(:,1)=-output(:,1); +% % output(:,2)= mod(output(:,2)+90,360)-90; +% [output(:,1),output(:,2),output(:,3)]=cart2sph(temp(:,1),temp(:,3),-temp(:,2)); +% [output(:,1),output(:,2)]=sph2hor(output(:,1),output(:,2)); + end +end + + + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m new file mode 100644 index 0000000000000000000000000000000000000000..9cb58cf9593fbb4a3f2d1c0fbc5dc67add2688f5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdbPath.m @@ -0,0 +1,35 @@ +function dbPath=SOFAdbPath(newPath) +% dbPath=SOFAdbPath(newPath) +% +% dbPath=SOFAdbPath returns the path to the directory containing +% HRTFs for demos and applications. The default path is: this_directory/../HRTFs/SOFA +% +% [...]=SOFAdbPath(newPath) sets the path to the directory for further calls +% of SOFAdbPath. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAstart +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedPath; + +if exist('newPath','var') + if strcmp(newPath,'reset') + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'HRTFs','SOFA'); + else + CachedPath=newPath; + end +elseif isempty(CachedPath) + % default: 'this_directory/../HRTFs/SOFA' + CachedPath=fullfile(fileparts(fileparts(mfilename('fullpath'))),'HRTFs','SOFA'); +end +dbPath=CachedPath; + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m new file mode 100644 index 0000000000000000000000000000000000000000..ba17308dab105a995a29dc8d681cf70c7c667fd1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdbURL.m @@ -0,0 +1,32 @@ +function dbURL=SOFAdbURL(dbURL) +% dbURL=SOFAdbURL +% +% dbURL=SOFAdbURL returns the internet URL to the directory containing +% HRTFs. The default URL is http://www.sofacoustics.org/data. +% +% dbURL=SOFAdbURL(newURL) sets the internet URL to the newURL for further calls +% of SOFAdbURL. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAdbURL +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +persistent CachedURL; + +if exist('dbURL','var') + if strcmp(dbURL,'reset') + CachedURL='http://www.sofacoustics.org/data'; + else + CachedURL=dbURL; + end +elseif isempty(CachedURL) + CachedURL='http://www.sofacoustics.org/data'; +end +dbURL=CachedURL; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m new file mode 100644 index 0000000000000000000000000000000000000000..d8cf1c7130e7ae73636cb77218e779ba99d328e6 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAdefinitions.m @@ -0,0 +1,83 @@ +function output = SOFAdefinitions(varargin) +% output = SOFAdefinitions(varargin) +% +% SOFAdefinitions returns a struct containing definitions like the time +% format used in the API. +% +% SOFAdefinitions('dateFormat') returns the date format +% +% SOFAdefinitions('APIName') returns the APIName +% +% SOFAdefinitions('dimensions') returns the dimensions used in the API +% +% SOFAdefinitions('EOL') returns the end-of-line separator used in the API +% +% SOFAdefinitions('dateReference') returns the string with the reference +% for the date when stored as numeric (number of seconds elapsed) +% +% SOFAdefinitions('units') returns the units and their corresponding aliases +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAdefinitions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +definput.flags.type={'all','dateFormat','APIName','dimensions','EOL','dateReference','units'}; +[flags,kv]=SOFAarghelper({},definput,varargin); + +%% Return all definitions in a structure +if flags.do_all, + output.APIName = SOFAdefinitions('APIName'); + output.dateFormat = SOFAdefinitions('dateFormat'); + output.dimensions = SOFAdefinitions('dimensions'); + output.EOL = SOFAdefinitions('EOL'); + output.dateReference = SOFAdefinitions('dateReference'); + output.units=SOFAdefinitions('units'); +end + +%% name of the API +if flags.do_APIName, + output = 'ARI SOFA Toolbox for Matlab/Octave'; +end + +%% date string to use (see help datestr) +if flags.do_dateFormat, + output = 'yyyy-mm-dd HH:MM:SS'; +end + +%% EOL to use +if flags.do_EOL, + output = char(10); +end + +%% dimensions to use +if flags.do_dimensions, + output.M = 'M'; % Number of Measurements + output.R = 'R'; % Number of Receivers + output.N = 'N'; % Number of Samples or the way you represent your data + output.E = 'E'; % Number of Emitters + output.C = 'C'; % Coordinates + output.I = 'I'; % Singleton + output.S = 'S'; % size of the largest string +end + +%% reference for date when used as numeric (number of seconds elapsed) +if flags.do_dateReference, + output = '1970-01-01 00:00:00'; +end + +%% return units with defined aliases +if flags.do_units, + output.metre={'metres','meter','meters'}; + output.degree={'degrees'}; + output.second={'seconds'}; +end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m new file mode 100644 index 0000000000000000000000000000000000000000..e70a93b875909b89d2a09ba60ffd5b3c87dcaeec --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAexpand.m @@ -0,0 +1,137 @@ +function [Obj, log] = SOFAexpand(Obj,VarName) +%SOFAexpand +% Obj = SOFAexpand(Obj) expands the singleton dimensions of all variables. +% Only variables will be expanded. Data and attributes won't. Note that Obj.API.Dimensions will be updated to the new dimensions. +% +% Obj = SOFAexpand(Obj,VarName) expands the singleton dimensions of the variable VarName. +% +% [Obj,log] = SOFAexpand(...) returns a log of expanded variables. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAexpand +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +log={''}; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj,'nodata'); + +%% If VarName given, expand a single variable only +if ~exist('VarName','var'), + + %% Expand all variables + % create field names which should have dimensions + X=rmfield(Obj,{'Data','API'}); + if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end + Xf=fieldnames(X); + + % Update the dimensions structure w/o data + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.(Xf{ii})=varNew; + Obj.API.Dimensions.(Xf{ii})=dimNew; + log{end+1}=[Xf{ii} ' expanded to ' dimNew]; + end + end + + % Expand the dimensions of Data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if ~isempty(strfind(Xf{ii},'_')), continue; end; % is an attribute --> not expandable + if ~isfield(OC.API.Dimensions.Data, Xf{ii}), continue; end; % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(Xf{ii}); % all possible dimensions + if ~iscell(dim), continue; end; % is a variable with a single dimension definition --> not expandable + if numel(dim)==1, continue; end; % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,Xf{ii},dim); + if ~isempty(varNew), + Obj.Data.(Xf{ii})=varNew; + Obj.API.Dimensions.Data.(Xf{ii})=dimNew; + log{end+1}=['Data.' Xf{ii} ' expanded to ' dimNew]; + end + end + + +else % Expand a single variable only + if isempty(strfind(VarName,'_')), % is an attribute --> not expandable + if strncmp(VarName,'Data.',length('Data.')) + % variable within the Data. structure + VarName=VarName(length('Data.')+1:end); + if isfield(OC.API.Dimensions.Data, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.Data.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expandData(Obj,VarName,dim); + if ~isempty(varNew), + Obj.Data.(VarName)=varNew; + Obj.API.Dimensions.Data.(VarName)=dimNew; + log{end+1}=['Data.' VarName ' expanded to ' dimNew]; + end + end + end + else + if isfield(OC.API.Dimensions, VarName), % is a used-defined variable --> not expandable + dim=OC.API.Dimensions.(VarName); % all possible dimensions + if iscell(dim), % is a variable with a single dimension definition --> not expandable + [varNew,dimNew]=expand(Obj,VarName,dim); + if ~isempty(varNew), + Obj.(VarName)=varNew; + Obj.API.Dimensions.(VarName)=dimNew; + log{end+1}=[VarName ' expanded to ' dimNew]; + end + end + end + end + end +end + +%% log variable +if length(log)>1, log=log(2:end); else log={}; end; + +%% expand a single variable +% Obj: the full SOFA object +% f: name of the variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expand(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.(f),ones([getdim(Obj,dN) 1])); + end + if ~exist('var','var'), var=[]; dN=[]; end; +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); + +%% expand a single Data variable +% Obj: the full SOFA object +% f: name of the Data variable +% dims: allowed dimensions of that variable (cell array) +% var: expanded variable, or empty if nothing happened +% dN: new dimension, or empty if nothing happened +function [var,dN]=expandData(Obj,f,dims) + d=cell2mat(strfind(dims,'I')); % all choices for a singleton dimensions + for jj=1:length(d) % loop through all expandable dimensions + len=size(Obj.Data.(f),d(jj)); % size of the considered dimension + if len>1, continue; end; % the expandable dimension is already expanded + dN=dims{cellfun('isempty',strfind(dims,'I'))==1}; + var=bsxfun(@times,Obj.Data.(f),ones([getdim(Obj,dN) 1])); + end + if ~exist('var','var'), var=[]; dN=[]; end; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m new file mode 100644 index 0000000000000000000000000000000000000000..66a7a03b20af0db83d99642ba735336217235e15 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAfind.m @@ -0,0 +1,47 @@ +function [idx, azinew, elenew, rnew] = SOFAfind(Obj,azi,ele,r) +% SOFAfind +% [idx, azi, ele, r] = SOFAfind(Obj, azi, ele, r) finds the indecies to +% the HRTFs from OBJ according to the trajectory given in AZI, ELE, R. +% Input: +% Obj: SOFA object containing HRTFs +% azi, ele: direction (in degrees) for azimuth and elevation +% r: optional radius. If not provided, radius will be ignored. +% +% Output: +% idx: index of the filters (corresponds to AZI and ELE) +% azi, ele: azimuth and elevation of the actual position (degrees) +% r: actual radius +% + +% #Author: Piotr Majdak (2019) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - SOFAfind +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + +%% create a 2D-grid with nearest positions +if ~exist('r','var'), + r=1; + Obj.SourcePosition(:,3)=r; +end +pos=SOFAconvertCoordinates(Obj.SourcePosition,'spherical','cartesian'); +idx=zeros(length(azi),1); +for ii=1:length(azi) + [t(:,1),t(:,2),t(:,3)] = sph2cart(deg2rad(azi(ii)),deg2rad(ele(ii)),r); + dist = sum((pos-repmat(t,size(pos,1),1)).^2,2); + [~,idx(ii)]=min(dist); +end + +%% Output +% actually used angles +azinew = Obj.SourcePosition(idx,1); +elenew = Obj.SourcePosition(idx,2); +rnew = Obj.SourcePosition(idx,3); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..4eef2508553f6bd0c0ac892efc16b878d22b6f3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAgetConventions.m @@ -0,0 +1,139 @@ +function Obj = SOFAgetConventions(sofaconventions,flags,version) +%SOFAgetConventions +% +% List = SOFAgetConventions() returns a list with supported conventions. +% +% Obj = SOFAgetConventions(sofaconvention) returns a SOFA object +% with all metadata and data for the corresponding sofaconvention. Obj +% will be empty if sofaconventions is not supported. +% +% Obj = SOFAgetConventions(sofaconvention, flags) returns only selected +% metadata for the corresponding sofaconvention with the following encoding: +% m: mandatory +% r: readonly +% a: all (default) +% +% Obj = SOFAgetConventions(sofaconvention, version) returns only the selected +% version of the convention. +% +% Obj = SOFAgetConventions(sofaconvention, flag, version) returns only the selected +% version and metadata. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc & header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAgetConventions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Cache +persistent AllObj; + +%% If flags not provided, return the conventions with all metadata +if ~exist('version','var') + if ~exist('flags','var') + flags='a'; % no flags, no version --> flags = a, version = any. + else + switch flags % no version, check if flags is flags or version + case {'a', 'm', 'r'} + % flags is flags --> do nothing + otherwise + version=flags; % flags is version --> copy to version + flags='a'; + end + end +end + + +%% If sofaconventions not provided, return the list with supported conventions +if ~exist('sofaconventions','var') + p=mfilename('fullpath'); + d=dir([p(1:length(p)-length(mfilename)) 'conventions' filesep '*_m_*.mat']); + Obj={}; + for ii=1:length(d) + dn=d(ii).name; + idx=strfind(dn,'_'); + Obj{ii,1}=dn(1:idx(1)-1); + end + Obj=unique(Obj); + AllObj=[]; + return; +end + +%% Load cached object + +if isfield(AllObj,flags) + if isfield(AllObj.(flags).Obj,'GLOBAL_SOFAConventions') + if strcmp(AllObj.(flags).Obj.GLOBAL_SOFAConventions,sofaconventions) + if ~exist('version','var') + Obj=AllObj.(flags).Obj; % return cached convention object + else + if strcmp(AllObj.(flags).Obj.GLOBAL_SOFAConventionsVersion,version) + Obj=AllObj.(flags).Obj; % return cached convention object + end + end + end + end +end + +if ~exist('Obj','var') + % cached object not loaded yet + p=mfilename('fullpath'); + if exist('version','var') + % load a specific version but do not store in the cache + if ~isempty(dir([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '_' flags '_' version '.mat'])) + load([p(1:length(p)-length(mfilename)) 'conventions' filesep sofaconventions '_' flags '_' version '.mat']); + else + error(['Convention ' sofaconventions ' with the version ' version ' not found.']); + end + else + allver=dir(fullfile(p(1:length(p)-length(mfilename)), 'conventions' , [sofaconventions '_' flags '_*.mat'])); + if isempty(allver) + warning(['Convention ' sofaconventions ' not found.']'); + Obj=[]; + else + vermax='0.0'; + idxmax=0; + for ii=1:length(allver) + x=load([p(1:length(p)-length(mfilename)) 'conventions' filesep allver(ii).name]); + if compareversions(x.Obj.GLOBAL_SOFAConventionsVersion,vermax)>0 + vermax=x.Obj.GLOBAL_SOFAConventionsVersion; + idxmax=ii; + end + end + % store in cache + AllObj.(flags)=load([p(1:length(p)-length(mfilename)) 'conventions' filesep allver(idxmax).name]); + Obj=AllObj.(flags).Obj; % return the cached version + end + end +end + +%% Overwrite some special fields +if isfield(Obj,'GLOBAL_DateCreated'), Obj.GLOBAL_DateCreated=datestr(now,SOFAdefinitions('dateFormat')); end +if isfield(Obj,'GLOBAL_APIVersion'), Obj.GLOBAL_APIVersion=SOFAgetVersion; end +if isfield(Obj,'GLOBAL_APIName'), Obj.GLOBAL_APIName=SOFAdefinitions('APIName'); end + +end + +function res=compareversions(ver1, ver2) + + [~,maj1,min1]=fileparts(ver1); + [~,maj2,min2]=fileparts(ver2); + maj1=str2num(maj1); + min1=str2num(min1(2:end)); + maj2=str2num(maj2); + min2=str2num(min2(2:end)); + if maj1>maj2 + res=1; % ver1 > ver2 + elseif maj1==maj2 && min1>min2 + res=1; % ver1 > ver2 + elseif maj2==maj2 && min1==min2 + res=0; % ver1 == ver2 + else + res=-1; % ver < ver2 + end +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m new file mode 100644 index 0000000000000000000000000000000000000000..df4b8d814ad546db955081fbc1b4a55bb085c2d5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAgetVersion.m @@ -0,0 +1,29 @@ +function results = SOFAgetVersion(flag) +%SOFAGETVERSION +% version = SOFAgetVersion() returns the version of the SOFA Toolbox API +% +% version = SOFAgetVersion('API') does the same. +% +% version = SOFAgetVersion('SOFA') returns the version of the SOFA supported by this Toolbox API. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAgetVersion +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +if ~exist('flag','var') + flag='API'; +end + +switch flag + case 'API' + results = '2.0'; + case 'SOFA' + results = '2.0'; +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m new file mode 100644 index 0000000000000000000000000000000000000000..adc80e62a97661bbd6f14cea66311d770c0416bd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAinfo.m @@ -0,0 +1,87 @@ +function SOFAinfo(Obj) +% SOFAinfo(Obj) gathers (mandatory) information about the SOFA object and +% display it. For SimpleFreeFieldHRIR some more details are displayed. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Global fields + +disp('### SOFAinfo: ###') +disp([Obj.GLOBAL_Conventions ' ' Obj.GLOBAL_Version]) +disp(['Conventions: ' Obj.GLOBAL_SOFAConventions ' ' Obj.GLOBAL_SOFAConventionsVersion]) +disp(['API: ' Obj.GLOBAL_APIName ' ' Obj.GLOBAL_APIVersion]) +disp(['Data Type: ' Obj.GLOBAL_DataType]) +disp(['Room Type: ' Obj.GLOBAL_RoomType]) +disp(['Date Created: ' Obj.GLOBAL_DateCreated]) +disp(['Date Modified: ' Obj.GLOBAL_DateModified]) +disp(['Author Contact: ' Obj.GLOBAL_AuthorContact]) +disp(['Organization: ' Obj.GLOBAL_Organization]) +disp(['License: ' Obj.GLOBAL_License]) +disp(['Title: ' Obj.GLOBAL_Title]) + + +%% Conventions dependant fields + +switch Obj.GLOBAL_SOFAConventions + + case 'SimpleFreeFieldHRIR' +disp(['Datebase Name: ' Obj.GLOBAL_DatabaseName]) + disp(' ') + disp(['Measurement details (' Obj.GLOBAL_SOFAConventions '):']); + disp('--------------------'); + disp(['Number of azimuth angles: ' num2str(length(unique(Obj.SourcePosition(:,1))))]); + disp(['Number of elevation angles: ' num2str(length(unique(Obj.SourcePosition(:,2))))]); + disp(['Number of radii: ' num2str(length(unique(Obj.SourcePosition(:,3))))]); + if isfield(Obj.Data,'SamplingRate') + disp(['Sampling Rate: ' num2str(Obj.Data.SamplingRate) ' ' Obj.Data.SamplingRate_Units]) + + end + disp(['Listener Short Name: ' Obj.GLOBAL_ListenerShortName]) + + if size(Obj.ListenerPosition,1)==1 + disp(['Listener Position: ', num2str(Obj.ListenerPosition) ' ' Obj.ListenerPosition_Units]); + else + disp([num2str(size(Obj.ListenerPosition,1)) ' Listener Positions']); + disp([' from ' num2str(Obj.ListenerPosition(1,:)) ' [' Obj.ListenerPosition_Units ']']); + disp([' to ' num2str(Obj.ListenerPosition(end,:)) ' [' Obj.ListenerPosition_Units ']']); + end + + if size(Obj.ListenerView,1)==1 + disp(['Listener View: ', num2str(Obj.ListenerView) ' ' Obj.ListenerView_Units]); + else + disp([num2str(size(Obj.ListenerPosition,1)) ' Listener Views']); + disp([' from ' num2str(Obj.ListenerView(1,:)) ' [' Obj.ListenerView_Units ']']); + disp([' to ' num2str(Obj.ListenerView(end,:)) ' [' Obj.ListenerView_Units ']']); + end + + if size(Obj.ReceiverPosition,1)==1 + disp(['Receiver Position: ', num2str(Obj.ReceiverPosition) ' ' Obj.ReceiverPosition_Units]); + else + disp([num2str(size(Obj.ReceiverPosition,1)) ' Receiver Positions']); + disp([' from ' num2str(Obj.ReceiverPosition(1,:)) ' [' Obj.ReceiverPosition_Units ']']); + disp([' to ' num2str(Obj.ReceiverPosition(end,:)) ' [' Obj.ReceiverPosition_Units ']']); + end + disp(['Receiver Position Type: ' Obj.ReceiverPosition_Type]) + + if size(Obj.SourcePosition,1)==1 + disp(['Source Position: ', num2str(Obj.SourcePosition) ' ' Obj.SourcePosition_Units]); + else + disp([num2str(size(Obj.SourcePosition,1)) ' Source Positions']); + disp([' from ' num2str(Obj.SourcePosition(1,:)) ' [' Obj.SourcePosition_Units ']']); + disp([' to ' num2str(Obj.SourcePosition(end,:)) ' [' Obj.SourcePosition_Units ']']); + end + disp(['Source Position Type: ' Obj.SourcePosition_Type]) + otherwise + % fill with conventions and disp commands if you feel motivated +end + +disp('### end ###') diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..63192cfef57ac8d3a41745d2ce791fcc93ed9e37 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAload.m @@ -0,0 +1,187 @@ +function Obj = SOFAload(fn,varargin) +%SOFALOAD +% Obj = SOFAload(FN) reads the SOFA object OBJ with all data from a SOFA file FN. +% +% FN can point to a remote file (containing '://') or to a local file: +% Remote file: FN will be downloaded to a temporary directory and loaded. +% Local file: If existing, will be loaded. If not existing, it will be downloaded from the internet repository given by SOFAdbURL. For this, FN must begin with the local HRTF directory given by SOFAdbPath. +% +% Obj = SOFAload(FN,'nodata') ignores the "Data." variables and loads metadata only (variables and attributes). +% +% Obj = SOFAload(FN,[START COUNT]) loads only COUNT number of measurements (dimension M) beginning with the index START. For remote files, or local but not existing files, the full file will be downloaded. +% +% Obj = SOFAload(FN,[START1 COUNT1],DIM1,[START2 COUNT2],DIM2,...) loads only COUNT1 number of data in dimension DIM1 beginning with the index START1, COUNT2 number of data in dimension DIM2 with the index START2 and so on. +% +% Obj = SOFAload(FN,...,'nochecks') loads the file but does not perform any checks for correct conventions. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAload +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% ----- Input parameters ------------------------------------------------ +inputargs={}; % for setting flags with SOFAarghelper +pDims=''; % for partial loading +pDimRange=[]; % for partial loading +jj=1; kk=1; ll=1; +for ii=1:length(varargin) + if isnumeric(varargin{ii}) + pDimRange(jj,:)=varargin{ii}; + jj=jj+1; + if ii==1 + inputargs{kk}=varargin{ii}; + kk=kk+1; + end + elseif strfind('MREN',varargin{ii}) + pDims(ll)=varargin{ii}; + ll=ll+1; + elseif strcmp(varargin{ii},'nochecks') + inputargs{kk}=varargin{ii}; + elseif strcmp(varargin{ii},'nodata') + inputargs{kk}=varargin{ii}; + kk=kk+1; + end +end +if ~isempty(pDimRange) && isempty(pDims) + pDims='M'; +end + +% Set flags with SOFAarghelper +definput.keyvals.Index = []; +definput.flags.type = {'data','nodata'}; +definput.flags.data = {'checks','nochecks'}; +[flags,kv] = SOFAarghelper({'Index'},definput,inputargs); + +% Check number of input arguments for partial loading +if ~(length(pDims)==size(pDimRange,1) || isempty(kv.Index)) + error('Missing dimension or range for partial loading'); +end +% Check file name +fn = SOFAcheckFilename(fn); +% Check if local or remote and download if necessary +if strfind(fn,'://') + % remote path: download as temporary + newfn = [tempname '.sofa']; + urlwrite(fn, newfn); +else + newfn = fn; + if ~exist(fn,'file') % file does not exist? + warning('SOFA:load',['File not found: ' strrep(fn,'\','\\')]); + % local path: replace SOFAdbPath by SOFAdbURL, download to SOFAdbPath + if length(fn)>length(SOFAdbPath) % fn is longer than SOFAdbPath? + if strcmp(SOFAdbPath,fn(1:length(SOFAdbPath))) % fn begins with SOFAdbPath + % create dir if not existing + if ~exist(fileparts(newfn),'dir'), + [success,msg] = mkdir(fileparts(newfn)); + if success~=1, error(msg); end + end + webfn = fn(length(SOFAdbPath)+1:end); + webfn(strfind(webfn,'\'))='/'; + webfn = [SOFAdbURL regexprep(webfn,' ','%20')]; + disp(['Downloading ' fn(length(SOFAdbPath)+1:end) ' from ' SOFAdbURL]); + [f,stat] = urlwrite(webfn,fn); + if ~stat + error(['Could not download file: ' webfn]); + end + else % fn not existing and not beginning with SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + else % fn not existing and shorter than SOFAdbPath --> error + error(['Unable to read file ''' fn ''': no such file']); + end + end +end + + +%% ----- Load SOFA file -------------------------------------------------- +if flags.do_nodata + Obj = NETCDFload(newfn,'nodata'); +elseif flags.do_data + try + if isempty(kv.Index), + Obj = NETCDFload(newfn,'all'); + else + Obj = NETCDFload(newfn,pDimRange,pDims); + end + catch me + error(['Error loading the file: ' newfn 13 me.message]); + end +end + + +%% ----- Checking of loaded data ----------------------------------------- +% Return if no checks should be performed +if flags.do_nochecks + return; +else + + % ----- Check for SOFA conventions ----- + if ~isfield(Obj,'GLOBAL_Conventions') || ~strcmp(Obj.GLOBAL_Conventions,'SOFA') + error('File is not a valid SOFA file'); + end + if ~isfield(Obj,'GLOBAL_SOFAConventions') + error('Information about SOFA conventions is missing'); + end + try + ObjTemplate = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + if isempty(ObjTemplate), + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + catch + error(['Unsupported SOFA conventions: ' Obj.GLOBAL_SOFAConventions]); + end + + % ----- Check if DataType is present ----- + if ~isfield(Obj,'GLOBAL_DataType') + error('DataType is missing'); + end + + % ----- Check if mandatory variables are present ----- + for field = fieldnames(ObjTemplate)' + field = field{:}; + if ~isfield(Obj,field) + Obj.(field) = ObjTemplate.(field); + if ~strfind(field,'_') % if `_` is missing it is a dimension + Obj.API.Dimensions.(field) = ObjTemplate.API.Dimensions.(field); + end + warning('SOFA:load',[field ' was missing, set to default']); + end + end + + % ---- If data loaded, check for correct data format ----- + if ~flags.do_nodata + if ~isfield(Obj,'Data') + error('Data is missing'); + end + for field = fieldnames(ObjTemplate.Data)' + field = field{:}; + if ~isfield(Obj.Data,field) + Obj.Data.(field) = ObjTemplate.Data.(field); + Obj.API.Dimensions.Data.(field) = ... + ObjTemplate.API.Dimensions.Data.(field); + warning('SOFA:load',['Data.' field ' was missing, set to default']); + end + end + Obj = SOFAupdateDimensions(Obj); + end + + % Remove undesired attribute of NetCDF files, if existing + if isfield(Obj,'GLOBAL__NCProperties'), Obj=rmfield(Obj,'GLOBAL__NCProperties'); end + + % ----- Ensure backwards compatibility ----- + % TODO: is the while loop necessary, or could be handled just by calling + % SOFAupgradeConventions(Obj) once? + modified = 1; + while modified + [Obj,modified] = SOFAupgradeConventions(Obj); + end + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..36c5e5fbcdec7da9c6dd3157379052a793c274cd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAmerge.m @@ -0,0 +1,154 @@ +function [C, log] = SOFAmerge(A,B) +%SOFAmerge +% [C, log] = SOFAmerge(A, B) merges the SOFA objects A and B to a single one, C. +% +% A and B are structs containing the data and meta. A and B +% must be of the same SOFA conventions. +% +% C is a struct containing merged data +% log contains log data + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupdateDimensions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Initial check +if ~strcmp(A.GLOBAL_SOFAConventions,B.GLOBAL_SOFAConventions) + error('Both SOFA objects must use the same SOFA conventions'); +end +if A.API.N~=B.API.N + error('Data size of both SOFA objects must be the same'); +end +Def = SOFAdefinitions; +log={''}; +OC = SOFAgetConventions(A.GLOBAL_SOFAConventions,'a'); + +%% Update dimensions +A=SOFAupdateDimensions(A); +B=SOFAupdateDimensions(B); + +%% create field names which have to be checked +C=rmfield(B,{'API','Data'}); +if isfield(C,'PRIVATE'), C=rmfield(C,'PRIVATE'); end +Bf=fieldnames(C); + +%% Copy and merge metadata variables +C=A; +for ii=1:size(Bf,1) + if ~isfield(A,Bf{ii}) + C.(Bf{ii}) = B.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.(Bf{ii}),B.(Bf{ii})), + C.(Bf{ii}) = B.(Bf{ii}); % content the same, no conflict + else + switch Bf{ii} + case 'GLOBAL_TimeCreated' % use the oldest date + dateNew=datenum(A.GLOBAL_TimeCreated,Def.dateFormat); + if datenum(B.GLOBAL_TimeCreated,Def.dateFormat)<dateNew, dateNew=datenum(B.GLOBAL_TimeCreated,Def.dateFormat); end; + C.(Bf{ii}) = datestr(dateNew,Def.dateFormat); + log{end+1}=[Bf{ii} ' set to ' C.(Bf{ii})]; + case 'GLOBAL_TimeModified' % now + C.(Bf{ii}) = datestr(now,Def.dateFormat); + log{end+1}=[Bf{ii} ' updated']; + otherwise + C.(Bf{ii}) = [A.(Bf{ii}) '; ' B.(Bf{ii})]; % concatate [A; B] + log{end+1}=[Bf{ii} ' merged']; + end + end + else % a variable + if isfield(OC.API.Dimensions, Bf{ii}) % is a known variable? + AExp=SOFAexpand(A,Bf{ii}); + BExp=SOFAexpand(B,Bf{ii}); + dim=strfind(AExp.API.Dimensions.(Bf{ii}),'M'); + if isempty(dim), + error([Bf{ii} ' can not be merged because it does not depend on M']); + end + C.(Bf{ii})=cat(dim,AExp.(Bf{ii}),BExp.(Bf{ii})); + log{end+1}=[Bf{ii} ' expanded and merged']; + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions, Bf{ii}) + error(['Dimension missing for ' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.(Bf{ii}),'M'); + if ~isempty(dim), + C.(Bf{ii})=cat(dim,A.(Bf{ii}),B.(Bf{ii})); % depends on M, merge + log{end+1}=[Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.(Bf{ii})==B.(Bf{ii}))==1, + C.(Bf{ii})=A.(Bf{ii}); + log{end+1}=[Bf{ii} ' identical']; + else + error([Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Copy and merge Data variables +Bf=fieldnames(B.Data); +for ii=1:size(Bf,1) + if ~isfield(A.Data,Bf{ii}) + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % field in B but not in A. Simple copy. + else % here we have a potential conflict and have to merge + if strfind(Bf{ii},'_') % is it an attribute? + if strcmp(A.Data.(Bf{ii}),B.Data.(Bf{ii})), + C.Data.(Bf{ii}) = B.Data.(Bf{ii}); % content the same, no conflict + else + C.Data.(Bf{ii}) = [A.Data.(Bf{ii}) '; ' B.Data.(Bf{ii})]; % concatate [A; B] + log{end+1}=['Data.' Bf{ii} ' merged']; + end + else % a variable in Data + if isfield(OC.API.Dimensions.Data,Bf{ii}) % is a known variable? + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); % is a matrix + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if all(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + else % user-defined variable, dimensions must be stated + if ~isfield(A.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in A.']); end + if ~isfield(B.API.Dimensions.Data, Bf{ii}) + error(['Dimension missing for Data.' Bf{ii} ' in B.']); end + dim=strfind(A.API.Dimensions.Data.(Bf{ii}),'M'); + if ~isempty(dim), + C.Data.(Bf{ii})=cat(dim,A.Data.(Bf{ii}),B.Data.(Bf{ii})); % depends on M, cat + log{end+1}=['Data.' Bf{ii} ' merged']; + else % not M-dependend, must be identical in A and B + if prod(A.Data.(Bf{ii})==B.Data.(Bf{ii}))==1, + C.Data.(Bf{ii})=A.Data.(Bf{ii}); + log{end+1}=['Data.' Bf{ii} ' identical']; + else + error(['Data.' Bf{ii} ' must depend on M or be equal in both objects.']); + end + end + end + end + end +end + +%% Update the new dimensions and finish +C=SOFAcompact(C); +C=SOFAupdateDimensions(C); +if length(log)>1, log=log(2:end); else log={}; end; + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.API.(f)),upper(str)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m new file mode 100644 index 0000000000000000000000000000000000000000..7541ffac9f25356c5ccfc7e8e15dc9b92e6cd945 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAplotGeometry.m @@ -0,0 +1,463 @@ +function SOFAplotGeometry(Obj,varargin) +% SOFAplotGeometry(Obj) plots the geometry found in the Obj. +% +% SOFAplotGeometry(Obj, index) plots the geometry for the measurements +% given in the index. +% +% Supported conventions: +% SimpleFreeFieldHRIR +% SimpleFreeFieldHRTF +% SingleRoomDRIR +% FreeFieldDirectivityTF +% some special cases of GeneralFIR. +% +% Parameter +% 'index' measurement to be plotted. Default: 1:Obj.API.M +% 'normalize' normalize view and up vectors +% 'SHorder' order of spherical harmonics +% 'SHm' m of shperical harmonics +% 'normalize' normalize view and up vectors +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: bug fixed when extracting LU (listener up) coordinates (28.12.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.keyvals.index=1:Obj.API.M; +definput.keyvals.shorder=Inf; +definput.keyvals.shm=Inf; +definput.flags.normalize={'normalize'}; +argin=varargin; +for ii=1:length(argin) + if ischar(argin{ii}), argin{ii}=lower(argin{ii}); end +end +[flags,kv] = SOFAarghelper({'index','shorder','shm'},definput,argin); +index = kv.index; +SHorder=kv.shorder; +SHm=kv.shm; +flags.do_normalize = flags.normalize; + +if any(index > Obj.API.M) + error(['Index out of range. Only ', num2str(Obj.API.M), ... + ' measurement(s) performed.']) +elseif any(index < 1) + error('Choose index to be >= 1.') +end + +switch Obj.GLOBAL_SOFAConventions +%% + case {'SimpleFreeFieldHRTF','SimpleFreeFieldHRIR','SingleRoomDRIR','FreeFieldDirectivityTF','GeneralFIR','GeneralTFE','FreeFieldHRIR','FreeFieldHRTF','GeneralTF-E'} + % Expand entries to the same number of measurement points + Obj = SOFAexpand(Obj); + % See if the room geometry is specified + if strcmpi(Obj.GLOBAL_RoomType,'shoebox') + x = min(Obj.RoomCornerA(1), Obj.RoomCornerB(1)); + xd = max(Obj.RoomCornerA(1), Obj.RoomCornerB(1)); + y = min(Obj.RoomCornerA(2), Obj.RoomCornerB(2)); + yd = max(Obj.RoomCornerA(2), Obj.RoomCornerB(2)); + w = xd - x; + h = yd - y; + figure('Position',[1 1 w*1.2 h]*100); + box on; hold on; + % plot the room + rectangle('Position',[x y w h]); + else + figure; hold on; + end + + legendEntries = []; + title(sprintf('%s, %s',Obj.GLOBAL_SOFAConventions,Obj.GLOBAL_RoomType)); + % Get ListenerPosition, ReceiverPosition, SourcePosition, and + % EmitterPosition + % NOTE: ListenerPosition is set to [0 0 0] for SimpleFreeFieldHRIR + LP = SOFAconvertCoordinates(Obj.ListenerPosition(index,:),Obj.ListenerPosition_Type,'cartesian'); + if ~(strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics')) + if size(Obj.ReceiverPosition,3)==1, idx=1; else idx=index; end + RP = SOFAconvertCoordinates(Obj.ReceiverPosition(:,:,idx),Obj.ReceiverPosition_Type,'cartesian'); + end + if size(Obj.SourcePosition,1)==1, idx=1; else idx=index; end + SP = SOFAconvertCoordinates(Obj.SourcePosition(idx,:),Obj.SourcePosition_Type,'cartesian'); + if ~(strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics')) + if size(Obj.EmitterPosition,3)==1, idx=1; else idx=index; end + EP = SOFAconvertCoordinates(Obj.EmitterPosition(:,:,idx),Obj.EmitterPosition_Type,'cartesian'); + end + if isfield(Obj,'ListenerView') + if size(Obj.ListenerView,1)==1, idx=1; else idx=index; end + LV = SOFAconvertCoordinates(Obj.ListenerView(idx,:),Obj.ListenerView_Type,'cartesian'); + end + if isfield(Obj,'ListenerUp') + try + if size(Obj.ListenerUp,1)==1, idx=1; else idx=index; end + LU = SOFAconvertCoordinates(Obj.ListenerUp(idx,:),Obj.ListenerUp_Type,'cartesian'); + catch + % if listerUp_type is not defined try using listenerView_type + % instead + if size(Obj.ListenerUp,1)==1, idx=1; else idx=index; end + LU = SOFAconvertCoordinates(Obj.ListenerUp(idx,:),Obj.ListenerView_Type,'cartesian'); + end + end + if isfield(Obj,'SourceView') + if size(Obj.SourceView,1)==1, idx=1; else idx=index; end + SV = SOFAconvertCoordinates(Obj.SourceView(idx,:),Obj.SourceView_Type,'cartesian'); + end + if isfield(Obj,'SourceUp') + try + if size(Obj.SourceUp,1)==1, idx=1; else idx=index; end + SU = SOFAconvertCoordinates(Obj.SourceUp(idx,:),Obj.SourceUp_Type,'cartesian'); + catch + if size(Obj.SourceUp,1)==1, idx=1; else idx=index; end + SU = SOFAconvertCoordinates(Obj.SourceUp(idx,:),Obj.SourceView_Type,'cartesian'); + end + end + % Use only unique listener and source positons + caseString = ''; + uniquePoints = [LP SP]; + if exist('LV') + uniquePoints = [uniquePoints LV]; + caseString = strcat(caseString , 'LV'); + end + if exist('LU') + uniquePoints = [uniquePoints LU]; + caseString = strcat(caseString, 'LU'); + end + if exist('SV') + uniquePoints = [uniquePoints SV]; + caseString = strcat(caseString, 'SV'); + end + if exist('SU') + uniquePoints = [uniquePoints SU]; + caseString = strcat(caseString, 'SU'); + end + + uniquePoints = unique(uniquePoints,'rows'); + switch caseString + case '' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + case 'LV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + case 'LVLU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); +% LU = uniquePoints(:,7:9); % I think this was a bug (miho) + LU = uniquePoints(:,10:12); + case 'LVLUSV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + LU = uniquePoints(:,10:12); + SV = uniquePoints(:,13:15); + case 'SV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + SV = uniquePoints(:,7:9); + case 'SVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + SV = uniquePoints(:,7:9); + SU = uniquePoints(:,10:12); + case 'LVSV' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + SV = uniquePoints(:,10:12); + case 'LVSVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + SV = uniquePoints(:,10:12); + SU = uniquePoints(:,13:15); + case 'LVLUSVSU' + LP = uniquePoints(:,1:3); + SP = uniquePoints(:,4:6); + LV = uniquePoints(:,7:9); + LU = uniquePoints(:,10:12); + SV = uniquePoints(:,13:15); + SU = uniquePoints(:,16:18); + otherwise + error('This SOFAConventions is not supported for plotting'); + end + + % Plot ListenerPosition + legendEntries(end+1) = plot3(LP(:,1),LP(:,2),LP(:,3),'ro','MarkerFaceColor','r','MarkerSize',5); + if strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics') + maxSHorder = sqrt(Obj.API.R)-1; + % set SHorder to max if user didn't specify it + if isinf(SHorder) + SHorder = maxSHorder; + end + % check if chosen SHorder is possible + if SHorder > maxSHorder + error(['Chosen SHorder not possibile, only orders up to ', ... + num2str(maxSHorder), ' possible.']) + elseif SHorder < 0 + error('Chosen SHorder not possibile, as it must be positive.') + end + x0 = Obj.ListenerPosition(1,1); + y0 = Obj.ListenerPosition(1,2); + z0 = Obj.ListenerPosition(1,3); + + % check for m given by the user and if it is possible + if isinf(SHm) + % if not set to some value + SHm = -floor(1/2 * SHorder); + elseif abs(SHm) > SHorder + error(['Chosen SHm not possibile, must be in range of abs(', ... + num2str(SHorder), ').']) + end + % if possibile set SHmForPlotting + SHmForPlotting = power(SHorder,2)+SHorder+SHm+1; + + [X,Y,Z] = sphere(50); + [azi_rad,elev_rad,~] = cart2sph(X,Y,Z); + azi_length =size(azi_rad,1); + elev_length=size(elev_rad,1); + azi= azi_rad/pi*180; + elev = elev_rad/pi*180; + azi = azi(:); + elev = elev(:); + + S = sph2SH([azi,elev], SHorder); + S = S(:,SHmForPlotting); + S = reshape(S,[azi_length,elev_length]); + + r_sphere = 0.7*max(max(S))*randi(2,size(S)); + r = abs(S) + r_sphere; + + [D_x,D_y,D_z] = sph2cart(azi_rad,elev_rad,abs(r)); + legendEntries(end+1) = surf(D_x+x0,D_y+y0,D_z+z0,Y,'LineStyle','none','FaceAlpha',0.09); +% elseif strcmpi(Obj.ReceiverPosition_Type,'spherical') +% S = sqrt(Obj.API.R-1); +% x0 = Obj.ListenerPosition(1,1); +% y0 = Obj.ListenerPosition(1,2); +% theta = -pi : 0.01 : pi; +% r = 1; +% phi = sin(S*theta); +% phi_negativ = sin(-S*theta); +% +% [x,y] = pol2cart(theta,(r*(1+ abs(phi)+ abs(phi_negativ)))./3); +% legendEntries(end+1)=plot(x+x0,y+y0,'LineStyle','--','Color',[0.741 0.747 0.741]); +% +% % text(x0,y0+r,['Order: ',num2str(S)],'HorizontalAlignment',... +% % 'center','VerticalAlignment','bottom') + + else + % Plot ReceiverPositon (this is plotted only for the first ListenerPosition) + if ndims(RP)>2 + % If ReceiverPosition has more than two dimensions reduce it to the first + % ListenerPosition + RP = shiftdim(RP,2); + RP = squeeze(RP(1,:,:)); + RP = reshape(RP,[size(Obj.ReceiverPosition,1), Obj.API.C]); + end + legendEntries(end+1) = plot3(LP(1,1)+RP(1,1), LP(1,2)+RP(1,2), LP(1,3)+RP(1,3),'r*','MarkerSize',8); + for ii=2:size(RP,1) + plot3(LP(1,1)+RP(ii,1), LP(1,2)+RP(ii,2), LP(1,3)+RP(ii,3),'r*','MarkerSize',8); + end + end + % Plot SourcePosition + legendEntries(end+1)=plot3(SP(:,1),SP(:,2),SP(:,3),'bd','MarkerSize',7); + % Plot EmitterPositions depending on Type + if strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics') + maxSHorder = sqrt(Obj.API.E)-1; + % set SHorder to max if user didn't specify it + if isinf(SHorder) + SHorder = maxSHorder; + end + % check if chosen SHorder is possible + if SHorder > maxSHorder + error(['Chosen SHorder not possibile, only orders up to ', ... + num2str(maxSHorder), ' possible.']) + elseif SHorder < 0 + error('Chosen SHorder not possibile, as it must be positive.') + end + x0 = Obj.SourcePosition(1,1); + y0 = Obj.SourcePosition(1,2); + z0 = Obj.SourcePosition(1,3); + + % check for m given by the user + if isinf(SHm) + SHm = -floor(1/2 * SHorder); + elseif abs(SHm) > SHorder + error(['Chosen SHm not possibile, must be in range of abs(', ... + num2str(SHorder), ').']) + end + % if possibile set SHmForPlotting + SHmForPlotting = power(SHorder,2)+SHorder+SHm+1; + + [X,Y,Z] = sphere(50); + [azi_rad,elev_rad,~] = cart2sph(X,Y,Z); + azi_length =size(azi_rad,1); + elev_length=size(elev_rad,1); + azi= azi_rad/pi*180; + elev = elev_rad/pi*180; + azi = azi(:); + elev = elev(:); + + S = sph2SH([azi,elev], SHorder); + S = S(:,SHmForPlotting); + S = reshape(S,[azi_length,elev_length]); + + r_sphere = 0.7*max(max(S))*randi(2,size(S)); + r = abs(S) + r_sphere; + + [D_x,D_y,D_z] = sph2cart(azi_rad,elev_rad,abs(r)); + legendEntries(end+1) = surf(D_x+x0,D_y+y0,D_z+z0,Y,'LineStyle','none','FaceAlpha',0.09); + +% elseif strcmpi(Obj.EmitterPosition_Type,'spherical') +% S = sqrt(Obj.API.R-1); +% x0 = Obj.SourcePosition(1,1); +% y0 = Obj.SourcePosition(1,2); +% theta = -pi : 0.01 : pi; +% r = 1; +% phi = sin(S*theta); +% phi_negativ = sin(-S*theta); +% +% [x,y] = pol2cart(theta,(r*(1+ abs(phi)+ abs(phi_negativ)))./3); +% legendEntries(end+1)=plot(x+x0,y+y0,'LineStyle','--','Color',[0.741 0.747 0.741]); +% +% % text(x0,y0+r,['Order: ',num2str(S)],'HorizontalAlignment',... +% % 'center','VerticalAlignment','bottom') + + else + % Plot EmitterPosition + if ndims(EP)>2 + % If EmitterPosition has more than two dimensions reduce it to the first + % ListenerPosition + EP = shiftdim(EP,2); + EP = squeeze(EP(1,:,:)); + EP = reshape(EP,[size(Obj.EmitterPosition,1), Obj.API.C]); + end + % plot Emitters for first Source + legendEntries(end+1) = plot3(SP(1,1)+EP(1,1), SP(1,2)+EP(1,2), SP(1,3)+EP(1,3),'b+','MarkerSize',8); + for ii=2:size(EP,1) + plot3(SP(1,1)+EP(ii,1), SP(1,2)+EP(ii,2), SP(1,3)+EP(ii,3),'b+','MarkerSize',8); + end + % plot all Emitters for each Source + for jj=2:size(SP,1) + for ii=1:size(EP,1) + plot3(SP(jj,1)+EP(ii,1), SP(jj,2)+EP(ii,2), SP(jj,3)+EP(ii,3),'b+'); + end + end + end + if exist('LV','var') + % Plot ListenerView + LV=unique(LV,'rows'); + for ii = 2:size(LV,1) + % Scale size of ListenerView vector smaller + if flags.do_normalize + LV(ii,:) = LV(ii,:)./norm(LV(ii,:)); + end + % Plot line for ListenerView vector + quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LV(ii,1),LV(ii,2),LV(ii,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if flags.do_normalize + LV(1,:) = LV(1,:)./norm(LV(1,:)); + end + legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LV(1,1),LV(1,2),LV(1,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if exist('LU','var') + LU=unique(LU,'rows'); + for ii = 2:size(LU,1) + if flags.do_normalize + LU(ii,:) = LU(ii,:)./norm(LU(ii,:)); + end + quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LU(ii,1),LU(ii,2),LU(ii,3),0,'AutoScale','off','Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LU(ii,1),LU(ii,2),LU(ii,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% quiver3(LP(ii,1),LP(ii,2),LP(ii,3),LV(ii,1),LV(ii,2),LV(ii,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if flags.do_normalize + LU(1,:) = LU(1,:)./norm(LU(1,:)); + end + legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LU(1,1),LU(1,2),LU(1,3),0,'AutoScale','off','Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LU(1,1),LU(1,2),LU(1,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); +% legendEntries(end+1) = quiver3(LP(1,1),LP(1,2),LP(1,3),LV(1,1),LV(1,2),LV(1,3),'Color',[1 0 0],'MarkerFaceColor',[1 0 0]); + end + if exist('SV','var') + SV=unique(SV,'rows'); + % Plot ListenerView + for ii = 2:size(SV,1) + % Scale size of ListenerView vector smaller + if flags.do_normalize + SV(ii,:) = SV(ii,:)./norm(SV(ii,:)); + end + % Plot line for ListenerView vector + quiver3(SP(ii,1),SP(ii,2),SP(ii,3),SV(ii,1),SV(ii,2),SV(ii,3),0,... + 'AutoScale','off',... + 'Color',[0 0 1],'MarkerFaceColor',[0 0 1]); + end + if flags.do_normalize + SV(1,:) = SV(1,:)./norm(SV(1,:)); + end + legendEntries(end+1) = quiver3(SP(1,1),SP(1,2),SP(1,3),SV(1,1),SV(1,2),SV(1,3),0,... + 'AutoScale','off',... + 'Color',[0 0 1],'MarkerFaceColor',[0 0 1]); + end + if exist('SU','var') + SU=unique(SU,'rows'); + for ii = 2:size(SU,1) + if flags.do_normalize + SU(ii,:) = SU(ii,:)./norm(SU(ii,:)); + end + quiver3(SP(ii,1),SP(ii,2),SP(ii,3),SU(ii,1),SU(ii,2),SU(ii,3),0,... + 'AutoScale','off',... + 'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); + end + if flags.do_normalize + SU(1,:) = SU(1,:)./norm(SU(1,:)); + end + legendEntries(end+1) = quiver3(SP(1,1),SP(1,2),SP(1,3),SU(1,1),SU(1,2),SU(1,3),'Color',[0 0 0],'MarkerFaceColor',[0 0 0]); + end + % create legend + legendDescription = {'ListenerPosition'}; + if (strcmpi(Obj.ReceiverPosition_Type,'Spherical Harmonics')) + legendDescription{end+1} = ['Receiver (order: ', num2str(S_R) ,')']; + else + legendDescription{end+1} = 'ReceiverPosition'; + end + legendDescription{end+1} ='SourcePosition'; + if (strcmpi(Obj.EmitterPosition_Type,'Spherical Harmonics')) + legendDescription{end+1} = ['Emitter (order: ', num2str(SHorder),', m: ', num2str(SHm),')']; + else + legendDescription{end+1} = 'EmitterPosition'; + end + + if exist('LV','var') + legendDescription{end+1} = 'ListenerView'; + end + if exist('LU','var') + legendDescription{end+1} = 'ListenerUp'; + end + if exist('SV','var') + legendDescription{end+1} = 'SourceView'; + end + if exist('SU','var') + legendDescription{end+1} = 'SourceUp'; + end + legend(legendEntries,legendDescription,'Location','NorthEastOutside'); + xlabel(['X / ' Obj.ListenerPosition_Units]); + ylabel(['Y / ' Obj.ListenerPosition_Units]); + zlabel(['Z / ' Obj.ListenerPosition_Units]); + + otherwise + error('This SOFAConventions is not supported for plotting'); +end + +% Set fixed aspect ratio +axis equal; +% Add a little bit extra space at the axis +axisLimits = axis(); +paddingSpace = 0.2 * max(abs(axisLimits(:))); +axisLimits([1 3]) = axisLimits([1 3]) - paddingSpace; +axisLimits([2 4]) = axisLimits([2 4]) + paddingSpace; +axis(axisLimits); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..41f96a7d3cab820f164e0ac99fbf1cbb198598ea --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAplotHRTF.m @@ -0,0 +1,506 @@ +function [M,meta,h]=SOFAplotHRTF(Obj,type,varargin) +% SOFAplotHRTF(OBJ, TYPE, R, DIR, COLOR) plots the R receiver of HRTFs given in OBJ. +% The following TYPEs are supported: +% 'EtcHorizontal' energy-time curve in the horizontal plane (+/- THR) +% 'EtcMedian' energy-time curve in the median plane (+/- THR) +% 'MagHorizontal' magnitude spectra in the horizontal plane (+/- THR) +% 'MagMedian' magnitude spectra in the median plane (+/- THR) +% 'MagSpectrum' single magnitude spectrum for direction(s) DIR in COLOR +% 'MagSagittal' magnitude spectra in a sagittal plane specified by OFFSET +/- THR +% 'ITDhorizontal' interaural time delay in the horizontal plane (not +% supported in Octave) +% +% More options are available by SOFAplotHRTF(Obj,type,parameter,value) +% +% Parameters: +% 'receiver' receiver to be plotted. Default: 1 +% 'dir' fixes the positions to be plotted: +% [azi]: shows all direction for that azimuth +% [azi, ele]: shows all distances for that direction +% [azi, ele, distance]: shows only that position +% default: [0,0] +% 'offset' chooses a plane to be plotted. Default: 0 deg. +% 'thr' threshold for selecting positions around a plane. Default: 2 deg. +% 'floor' lowest amplitude shown (dB). Default: -50 dB. +% 'convert' convert to TF domain. Function should automatically choose if neccessary. Default: 0 if conversion is not necessary; 1 if conversion is neccessary. +% +% Additionally, 'b', 'r', 'g', etc. can be used for plotting in color +% as used by PLOT. +% +% +% Supported conventions: +% SimpleFreeFieldHRIR +% SimpleFreeFieldHRSOS +% SimpleFreeFieldHRTF +% SHFreeFieldHRTF +% some special cases of GeneralTF, GeneralTF-E. +% +% [M,meta,h]=SOFAplotHRTF... returns the matrix M and meta information about displayed in the figure. +% h is the handle of the plot. meta.idx is the index to the vectors actually plotted. +% +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: type ITDhorizontal added and updated (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: dependency on function 'npi2pi' removed (required toolbox in Matlab; in Octave not supported; outdated anyway) (08.02.2022) +% #Author: Michael Mihocic: keyvalue 'R'/'r' renamed to 'receiver' (10.05.2022) +% #Author: Michael Mihocic: 'do not convert' option enabled for SimpleFreeFieldHRTF convention; +% global title only displayed if 'Obj.GLOBAL_Title' not empty (30.05.2022) +% #Author: Michael Mihocic: plotting simplefreefieldhrtf fixed (in Octave); titles fixed when plotting magspectrum (02.06.2022) +% #Author: Michael Mihocic: plotting improved when data is available in TF format (more stable, no conversions by default); +% figure titles improved (04.07.2022) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% for backward compatibility (type as position-dependent input parameter) +if nargin == 3 && ischar(type) && isscalar(varargin{1}) +% varargin = flipud(varargin(:)); + R = varargin{1}; + flags.do_normalize=1; + dir=[0,0]; + color='b'; + thr=2; + offset=0; + noisefloor=-50; +% convert=1; more comples differing below: + + if exist('OCTAVE_VERSION','builtin') + % We're in Octave + if ismember(type,{'MagHorizontal','MagMedian','MagSpectrum','MagSagittal'}) && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) + % frequency domain input data only; for Octave the list has to be extended manually because 'contains' is not available + convert = 0; + else + convert = 1; + end + else + % We're in Matlab + if contains(lower(type),'mag') && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) + % frequency domain input data only + convert = 0; + else + convert = 1; + end + end + +else + definput.keyvals.receiver=1; + definput.keyvals.dir=[0,0]; + definput.keyvals.thr=2; + definput.keyvals.offset=0; + definput.keyvals.floor=-50; + definput.flags.color={'b','r','k','y','g','c','m'}; + definput.flags.level={'normalize','absolute'}; + definput.keyvals.convert=1; + argin=varargin; + for ii=1:length(argin) + if ischar(argin{ii}), argin{ii}=lower(argin{ii}); end + end + [flags,kv] = SOFAarghelper({'receiver','dir','thr','offset','floor'},definput,argin); + R = kv.receiver; + dir = kv.dir; + thr=kv.thr; + color = flags.color; + offset = kv.offset; + noisefloor=kv.floor; + convert=kv.convert; % force convert or not + +% if exist('OCTAVE_VERSION','builtin') +% % We're in Octave +% if ismember(type,{'MagHorizontal','MagMedian','MagSpectrum','MagSagittal'}) && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) +% % frequency domain input data only; for Octave the list has to be extended manually because 'contains' is not available +% convert=kv.convert; +% else +% convert = 1; +% end +% else +% % We're in Matlab +% if contains(lower(type),'mag') && ismember(lower(Obj.GLOBAL_SOFAConventions),{'freefielddirectivitytf','generaltf','simplefreefieldhrtf'}) +% % frequency domain input data only +% convert=kv.convert; +% else +% convert = 1; +% end +% end + +end + +meta=[]; + +if convert == 1 + %% Convert data to FIR + Obj=SOFAconvertConventions(Obj); + fs=Obj.Data.SamplingRate; + + %% check if receiver selection is possible + if R > size(Obj.Data.IR,2) + error(['Choosen receiver out of range. Only ', num2str(size(Obj.Data.IR,2)), ' receivers recorded.']) + end + titlepostfix=' (converted to IR)'; +else + %% check if receiver selection is possible + if R > size(Obj.Data.Real,2) + error(['Choosen receiver out of range. Only ', num2str(size(Obj.Data.Real,2)), ' receivers recorded.']) + end + titlepostfix=''; +end +if isfield(Obj, 'GLOBAL_Title') && isempty(Obj.GLOBAL_Title) == 0 + titleprefix = [Obj.GLOBAL_Title ': ']; +else + titleprefix = ''; +end + + +%% Convert to spherical if cartesian +if strcmp(Obj.SourcePosition_Type,'cartesian') +% % Obj2=Obj; % compare to old method (Obj2) + for ii=1:Obj.API.M + [Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)]=cart2sph(Obj.SourcePosition(ii,1),Obj.SourcePosition(ii,2),Obj.SourcePosition(ii,3)); +% [Obj2.SourcePosition(ii,1),Obj2.SourcePosition(ii,2),Obj2.SourcePosition(ii,3)]=cart2sph(Obj2.SourcePosition(ii,1),Obj2.SourcePosition(ii,2),Obj2.SourcePosition(ii,3)); + Obj.SourcePosition(ii,2)=rad2deg(Obj.SourcePosition(ii,2)); +% Obj2.SourcePosition(ii,2)=rad2deg(Obj2.SourcePosition(ii,2)); + Obj.SourcePosition(ii,1)=rad2deg(Obj.SourcePosition(ii,1)); +% Obj2.SourcePosition(ii,1)=rad2deg(Obj2.SourcePosition(ii,1)); + Obj.SourcePosition(ii,1)=mywrapTo180(Obj.SourcePosition(ii,1)); +% Obj2.SourcePosition(ii,1)=npi2pi(Obj2.SourcePosition(ii,1),'degrees'); % requires Mapping toolbox in Matlab + end + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degrees'; +end + +%% Plot according to the type +switch lower(type) + % Energy-time curve (ETC) in the horizontal plane + case 'etchorizontal' + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,R,:))); + pos=Obj.SourcePosition; + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,R)); + meta.idx=idx; + M2=noisefloor*ones(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + [azi,i]=sort(pos(:,1)); + M=M2(i,:); + if flags.do_normalize + M=M-max(max(M)); + end + M(M<=noisefloor)=noisefloor; + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.azi = azi; + h=surface(meta.time,azi,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Azimuth (deg)'); + title([titleprefix 'receiver: ' num2str(R)],'Interpreter','none'); + + % Magnitude spectrum in the horizontal plane + case 'maghorizontal' + pos=Obj.SourcePosition; % copy pos to temp. variable + pos(pos(:,1)>180,1)=pos(pos(:,1)>180,1)-360; % find horizontal plane + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); % find indices + pos=pos(idx,:); % truncate pos + meta.idx=idx; + if convert == 1 % converted + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + if flags.do_normalize + M=M-max(max(M)); % normalize + end + + M(M<noisefloor)=noisefloor; + [azi,i]=sort(pos(:,1)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.azi = azi; +% figure; + h=surface(meta.freq,azi,M(:,:)); + + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [azi,i]=sort(pos(:,1)); + M=M(i,:); +% figure; + + h=surface(Obj.N',azi,M); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Azimuth (deg)'); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magmedian' + azi=0; + pos=Obj.SourcePosition; + idx0=find(abs(pos(:,1))>90); + pos(idx0,2)=180-pos(idx0,2); + pos(idx0,1)=180-pos(idx0,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + pos=pos(idx,:); + meta.idx=idx; % PM: TODO: check if the correct index + + if convert == 1 % converted + + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + + h=surface(meta.freq,ele,M(:,:)); + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); +% figure; + h=surface(Obj.N',ele,M); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Elevation (deg)'); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Magnitude spectrum in the median plane + case 'magsagittal' + + [lat,pol]=sph2hor(Obj.SourcePosition(:,1),Obj.SourcePosition(:,2)); + pos=[lat pol]; + idx=find(pos(:,1)<(offset+thr) & pos(:,1)>(offset-thr)); + pos=pos(idx,:); + meta.idx=idx; + + if convert == 1 % converted + + hM=double(squeeze(Obj.Data.IR(:,R,:))); + M=(20*log10(abs(fft(hM(idx,:)')'))); + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + if flags.do_normalize + M=M-max(max(M)); + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.freq = 0:fs/size(hM,2):(size(M,2)-1)*fs/size(hM,2); + meta.ele = ele; + h=surface(meta.freq,ele,M(:,:)); + else + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + if flags.do_normalize + M=M-max(max(M)); % normalize + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + h=surface(Obj.N',ele,M(:,:)); + + end + shading flat + xlabel('Frequency (Hz)'); + ylabel('Polar angle (deg)'); + title([titleprefix 'receiver: ' num2str(R) '; Lateral angle: ' num2str(offset) 'deg' titlepostfix],'Interpreter','none'); + + + % ETC in the median plane + case 'etcmedian' +% noisefloor=-50; + azi=0; + Obj=SOFAexpand(Obj,'Data.Delay'); + hM=double(squeeze(Obj.Data.IR(:,R,:))); + pos=Obj.SourcePosition; + idx0=find(abs(pos(:,1))>90); + pos(idx0,2)=180-pos(idx0,2); + pos(idx0,1)=180-pos(idx0,1); + idx=find(pos(:,1)<(azi+thr) & pos(:,1)>(azi-thr)); + meta.idx=idx; % PM: TODO: Check if the correct index + M=(20*log10(abs(hM(idx,:)))); + pos=pos(idx,:); + del=round(Obj.Data.Delay(idx,R)); + M2=zeros(size(M)+[0 max(del)]); + for ii=1:size(M,1) + M2(ii,del(ii)+(1:Obj.API.N))=M(ii,:); + end + if flags.do_normalize + M=M2-max(max(M2)); + else + M = M2; + end + M(M<noisefloor)=noisefloor; + [ele,i]=sort(pos(:,2)); + M=M(i,:); + meta.time = 0:1/fs*1000:(size(M,2)-1)/fs*1000; + meta.ele = ele; + h=surface(meta.time,ele,M(:,:)); + set(gca,'FontName','Arial','FontSize',10); + set(gca, 'TickLength', [0.02 0.05]); + set(gca,'LineWidth',1); + cmap=colormap(hot); + cmap=flipud(cmap); + shading flat + colormap(cmap); + box on; + colorbar; + xlabel('Time (ms)'); + ylabel('Elevation (deg)'); + title([titleprefix 'receiver: ' num2str(R)],'Interpreter','none'); + + case 'magspectrum' + pos=round(Obj.SourcePosition*10)/10; + switch size(dir,2) + case 1 + aziPos = pos(:,1); + aziDir=dir(:,1); + aziComp = intersect(aziPos,aziDir,'rows'); + idx= find(ismember(aziPos,aziComp,'rows')); + case 2 + aziPos = pos(:,1); + aziDir=dir(:,1); + elePos = pos(:,2); + eleDir=dir(:,2); + aziComp = intersect(aziPos,aziDir,'rows'); + eleComp = intersect(elePos,eleDir,'rows'); + idx=find(ismember(aziPos,aziComp,'rows') & ... + ismember(elePos,eleComp,'rows')); + otherwise + aziPos = pos(:,1); + aziDir=dir(:,1); + elePos = pos(:,2); + eleDir=dir(:,2); + rPos = pos(:,3); + rDir=dir(:,3); + aziComp = intersect(aziPos,aziDir,'rows'); + eleComp = intersect(elePos,eleDir,'rows'); + rComp = intersect(rPos,rDir,'rows'); + idx=find(ismember(aziPos,aziComp,'rows') & ... + ismember(elePos,eleComp,'rows') & ismember(rPos,rComp,'rows')); + end + if isempty(idx), error('Position not found'); end + meta.idx=idx; + + if convert == 1 % convert + IR=squeeze(Obj.Data.IR(idx,R,:)); + if length(idx) > 1 + M=20*log10(abs(fft(IR')))'; + M=M(:,1:floor(size(M,2)/2)); % only positive frequencies + h=plot(0:fs/2/size(M,2):(size(M,2)-1)*fs/2/size(M,2),M); + for ii=1:length(idx) + labels{ii}=['#' num2str(idx(ii)) ': (' num2str(pos(idx(ii),1)) ', ' num2str(pos(idx(ii),2)) ')']; + end + legend(labels); + else % only one curve + hM=20*log10(abs(fft(IR))); + M=hM(1:floor(length(hM)/2)); + hold on; + h=plot(0:fs/2/length(M):(length(M)-1)*fs/2/length(M),M,color,... + 'DisplayName',['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + legend; + end + xlim([0 fs/2]); + titlepostfix=' (converted to IR)'; + else + + M=20*log10(abs(sqrt(squeeze(Obj.Data.Real(idx,R,:)).^2 + squeeze(Obj.Data.Imag(idx,R,:)).^2))); + + if length(idx) > 1 + h=plot(Obj.N',M); + for ii=1:length(idx) + labels{ii}=['#' num2str(idx(ii)) ': (' num2str(pos(idx(ii),1)) ', ' num2str(pos(idx(ii),2)) ')']; + end + legend(labels); + else + hold on; + h=plot(Obj.N',M,color,... + 'DisplayName',['#' num2str(idx) ': (' num2str(pos(idx,1)) ', ' num2str(pos(idx,2)) ')']); + legend; + end + titlepostfix=''; + end + ylabel('Magnitude (dB)'); + xlabel('Frequency (Hz)'); + ylim([max(max(M))+noisefloor-10 max(max(M))+10]); + title([titleprefix 'receiver: ' num2str(R) titlepostfix],'Interpreter','none'); + + % Interaural time delay in the horizontal plane + case 'itdhorizontal' + + if exist('OCTAVE_VERSION','builtin') + warning('Command ''polarplot'' not supported by Octave (yet)!') + else + [itd, ~] = SOFAcalculateITD(Obj, 'time'); + pos = Obj.SourcePosition; + idx=find(pos(:,2)<(offset+thr) & pos(:,2)>(offset-thr)); + itd = itd(idx); + meta.idx=idx; + [pos, idx_sort] = sort(pos(idx,1)); + itd = itd(idx_sort); + angles = deg2rad(pos); + %figure('Renderer', 'painters', 'Position', [10 10 700 450]); + polarplot(angles, itd, 'linewidth', 1.2); + ax = gca; + ax.ThetaDir = 'counterclockwise'; + ax.ThetaZeroLocation = 'top'; + rticks([max(itd)*2/3, max(itd)]); + rticklabels({[num2str(round(max(itd)*2/3*1e6,1)) ' ' char(181) 's'],... + [num2str(round(max(itd)*1e6,1)) ' ' char(181) 's']}); + thetaticks(0:30:330) + thetaticklabels({'0�', '30�', '60�', '90�', '120�', '150�', '180�', ... + '210�', '240�','270�', '300�', '330�'}); + grid on; + end + + otherwise + error([type , ' no supported plotting type.']) +end + + +% function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +% if rem(N,2)==0 +% f=[c; flipud(conj(c(2:end-1,:)))]; +% else +% f=[c; flipud(conj(c(2:end,:)))]; +% end +% f=real(ifft(f,N,1)); +% end + +function newangle = mywrapTo180(angle) + % transfer to range -180:180 + newangle = mod(angle+360, 360); + if newangle > 180 + newangle = newangle-360; + end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m new file mode 100644 index 0000000000000000000000000000000000000000..f34eb4981fe97bd882ed2beb59e3eed0d205eb83 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAremoveVariable.m @@ -0,0 +1,32 @@ +function Obj = SOFAremoveVariable(Obj,Name) +%SOFAremoveVariable +% Obj = SOFAremoveVariable(Obj,Name) removes the user-defined variable +% from the SOFA structure OBJ. NAME must be a string with the variable name +% ('API', 'PRIVATE', or 'GLOBAL' are not allowed). +% +% + +% #Author: Piotr Majdak: adapted from SOFAaddVariable (19.06.2019) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAremoveVariable +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +switch Name + case {'API','PRIVATE','GLOBAL','PRIVATE','Data'} + error('This variable name is reserved.'); + otherwise + if isfield(Obj,Name) + Obj=rmfield(Obj,Name); + if isfield(Obj.API.Dimensions,Name) + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,Name); + end + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..5773030f605cdbd2595fdf0635ccd146f2f66dd5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAsave.m @@ -0,0 +1,96 @@ +function [Obj] = SOFAsave(filename,Obj,varargin) +%SOFASAVE +% [Obj] = SOFAsave(filename,Obj,Compression) creates a new SOFA file and +% writes an entire data set to it. +% +% filename specifies the name of the SOFA file to which the data is written. +% Obj is a struct containing the data and meta +% data to be written to the SOFA file (see below for exact format). +% Compression is an optional numeric value between 0 and 9 specifying the +% amount of compression to be applied to the data when writing to the netCDF file. +% 0 is no compression and 9 is the most compression. +% +% The existence of mandatory variables will be checked. The dimensions +% will be updated. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc and header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAsave +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +Def = SOFAdefinitions; + +%% check file name +filename=SOFAcheckFilename(filename); + +%% Remove private data +if isfield(Obj,'PRIVATE'), Obj=rmfield(Obj,'PRIVATE'); end + +%% Check convention: mandatory variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'m'); + +varNames = fieldnames(ObjCheck); +for ii=1:size(varNames,1); + if ~isfield(Obj,varNames{ii}) + error(['Mandatory variable/attribute not existing: ' varNames{ii}]); + end +end + +%% Get & set dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Check convention: read-only variables +ObjCheck = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'r'); +varNames = fieldnames(ObjCheck); + +for ii=1:size(varNames,1); + if ischar(Obj.(varNames{ii})) + if ~strcmp(Obj.(varNames{ii}), ObjCheck.(varNames{ii})) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset from ' Obj.(varNames{ii}) ' to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + else + if Obj.(varNames{ii}) ~= ObjCheck.(varNames{ii}) + warning('SOFA:save',[varNames{ii} ' is read-only and was reset from ' Obj.(varNames{ii}) ' to ' ObjCheck.(varNames{ii})],0); + Obj.(varNames{ii})=ObjCheck.(varNames{ii}); + end + end +end + +%% check attributes (syntax, 1-dimensional string) +varNames = fieldnames(Obj); +for ii=1:size(varNames,1); + + if size(strfind(varNames{ii},'_'),2) == 1 + if ~ischar(Obj.(varNames{ii})) + error(['Attribute not a valid string: ' varNames{ii} ' = ' num2str(Obj.(varNames{ii}))]); + end + elseif size(strfind(varNames{ii},'_'),2) > 1 + error(['Attribute not valid (only one underscore "_" is allowed in attribute name): ' varNames{ii}]); + end + +end + +%% check varargin (compression) +if ~isempty(varargin) && isnumeric(varargin{1}) + if isscalar(varargin{1}) && varargin{1}>=0 && varargin{1}<=9 + Compression = varargin{1}; + else + error('Error: Compression must be a numeric scalar value between 0 and 9.'); + end +else + Compression = 1; % default +end + +%% Set/modify time information +Obj.GLOBAL_DateModified=datestr(now,Def.dateFormat); +if isempty(Obj.GLOBAL_DateCreated), Obj.GLOBAL_DateCreated=Obj.GLOBAL_DateModified; end + +%% Save file +NETCDFsave(filename,Obj,Compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..f4d978d1a0b0d4cb7721b2bf3fa8137e10f13d0e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAspat.m @@ -0,0 +1,112 @@ +function [out, azi, ele, idx] = SOFAspat(in,Obj,azi,ele) +% SOFAspat +% [out, azi, ele, idx] = SOFAspat(in, Obj, azi, ele) spatializes the sound IN using +% the HRTFs from OBJ according to the trajectory given in AZI and ELE. +% Input: +% in: vector with the sound +% Obj: SOFA object containing the HRTFs +% azi, ele: vectors with the trajectory (in degrees) independent for +% azimuth and elevation +% +% Output: +% out: binaural signal +% azi, ele: azimuth and elevation of the actual trajectory (degrees) +% idx: index of the filters (corresponds to AZI and ELE) +% +% This is an example of how to use SOFA. +% + +% #Author: Piotr Majdak (2013) +% #Author: Robert Baumgartner: adaptions (2016) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define required parameters +hop=0.5; % the hop size for the time-variant filtering (in fraction of the filter length) + +%% Initial checks +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + error('HRTFs must be saved in the SOFA conventions SimpleFreeFieldHRIR'); +end +if min(azi)<0, % Check for the required coordinate system + Obj.SourcePosition(:,1)=sph2nav(Obj.SourcePosition(:,1)); % if negative azimuths are required, swith to -90/+90 system +end +N=Obj.API.N; + +%% resize the input signal to be integer multiple of HRIR +L=length(in); +in=[in; zeros(N-mod(L,N),1)]; +L=length(in); % correct length of the input signal +S=L/N/hop; % number of segments to filter + +%% Resample the trajectory +if length(azi)>1, + azi= interp1(0:1/(length(azi)-1):1,azi,0:1/(S-1):1); +else + azi=repmat(azi,1,S); +end; +if length(ele)>1, + ele= interp1(0:1/(length(ele)-1):1,ele,0:1/(S-1):1); +else + ele=repmat(ele,1,S); +end; + +%% create a 2D-grid with nearest positions of the moving source +idx=zeros(S,1); +[target.x,target.y,target.z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(1,S)); +[pos.x,pos.y,pos.z] = sph2cart(deg2rad(Obj.SourcePosition(:,1)),... + deg2rad(Obj.SourcePosition(:,2)),Obj.SourcePosition(:,3)); +for ii=1:S % find nearest point on grid (LSP) + dist = (pos.x-target.x(ii)).^2 + (pos.y-target.y(ii)).^2 + (pos.z-target.z(ii)).^2; + [~,idx(ii)]=min(dist); +end + +%% normalize HRTFs to the frontal, eye-level position +% ii=find(Obj.SourcePosition(:,1)==0 & Obj.SourcePosition(:,2)==0); % search for position 0�/0� +% if isempty(ii) +% peak=max([sqrt(sum(Obj.Data.IR(:,1,:).*Obj.Data.IR(:,1,:))) sqrt(sum(Obj.Data.IR(:,2,:).*Obj.Data.IR(:,2,:)))]); % not found - normalize to IR with most energy +% else +% peak=([sqrt(sum(Obj.Data.IR(ii,1,:).*Obj.Data.IR(ii,1,:))) sqrt(sum(Obj.Data.IR(ii,2,:).*Obj.Data.IR(ii,2,:)))]); % found - normalize to this position +% end + +%% Spatialize +out=zeros(L+N/hop,2); +window=hanning(N); +ii=0; +jj=1; +iiend=L-N; +while ii<iiend + segT=in(ii+1:ii+N).*window; % segment in time domain + segF=fft(segT,2*N); % segment in frequency domain with zero padding + %----------- + segFO(:,1)=squeeze(fft(Obj.Data.IR(idx(jj),1,:),2*N)).*segF; + segFO(:,2)=squeeze(fft(Obj.Data.IR(idx(jj),2,:),2*N)).*segF; + %----------- + segTO=real(ifft(segFO)); % back to the time domain + out(ii+1:ii+2*N,:)=out(ii+1:ii+2*N,:)+segTO; % overlap and add + ii=ii+N*hop; + jj=jj+1; +end + +%% Normalize +% out(:,1)=out(:,1)/peak(1); +% out(:,2)=out(:,2)/peak(2); + +%% Output +% actually used angles +azi = Obj.SourcePosition(idx,1); +ele = Obj.SourcePosition(idx,2); +% upsampled for each sample +idup = floor(1:1/(N*hop):S+1-1/(N*hop)); +azi = azi(idup); +ele = ele(idup); + +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m new file mode 100644 index 0000000000000000000000000000000000000000..01a69bfdc557f701583d55931e79823eaec43f1f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAstart.m @@ -0,0 +1,117 @@ +function SOFAstart(flags) +% SOFAstart +% +% SOFAstart adds all needed pathes and checks if we need the Matlab or Octave +% version of the API +% +% SOFAstart(0) or SOFAstart('silent') will suppress any message during the start. +% SOFAstart ('short') will show a short header only during the start. +% SOFAstart ('full') will show all information, including all compiled +% conventions & versions. +% +% SOFAstart checks if SOFA has been started within the MATLAB session. If +% it is the case, SOFAstart skips all the initialization. If the initialization +% is required, SOFAstart('restart') performs the initialization in any case. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: 'full' flag added, changed order of display output messages (11.11.2021) +% #Author: Michael Mihocic: bug fixed when adding paths (29.11.2021) +% +% SOFA Toolbox - function SOFAstart +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Input parameters +verbose = 2; +restart = 0; +if nargin>0 + if strcmpi(flags,'silent'), verbose=0; end + if strcmpi(flags,'short'), verbose=1; end + if strcmpi(flags,'full'), verbose=3; end + if isnumeric(flags), if flags==0, verbose=0; end; end + if strcmpi(flags,'restart'), restart=1; end +end + +%% do not start when already started but not forced to restart +persistent started +if ~isempty(started) && ~restart + return; +end +started=1; +%% Check required support +if exist('OCTAVE_VERSION','builtin') + % We're in Octave + if compare_versions(OCTAVE_VERSION,'3.6.0','<=') % check if the octave version is high enough + error('You need Octave >=3.6.0 to work with SOFA.'); + end + pkg load netcdf + if ~which('test_netcdf') % check if octcdf is installed + error('You have to install the netcdf package in Octave to work with SOFA.'); + end +else + % We're in Matlab + if verLessThan('matlab','8') + warning('SOFA:start','SOFA for Matlab version <= 8 (2012b) not tested. Use on your risk.'); + end +end + + +%% Add Paths +% Get the basepath as the directory this function resides in. +% The 'which' solution below is more portable than 'mfilename' +% becase old versions of Matlab does not have "mfilename('fullpath')" +basepath=which('SOFAstart'); +basepath=basepath(1:end-12); % Kill the function name from the path. +f=filesep; + +% Add the base path and the needed sub-directories +% (basepath is added in case user navigated to this folder and changes dir) +if exist('addpath','file') || exist('addpath','builtin') % in Matlab it is a 'file'; in Octave it is a 'built-in' function + addpath(basepath,[basepath f 'helpers'],[basepath f 'coordinates'],[basepath f 'converters'],[basepath f 'demos'],[basepath f 'netcdf']); +else % in case "addpath" command is not available - can this ever be the case??? + path([basepath f 'helpers'],path); + path([basepath f 'coordinates'],path); + path([basepath f 'converters'],path); + path([basepath f 'demos'],path); + path([basepath f 'netcdf'],path); + path(path,basepath); +end + + +%% Provide SOFA conventions +dispOutput = SOFAcompileConventions; +convs = SOFAgetConventions; + +%% Display general informations + +if verbose + disp(['SOFA Matlab/Octave API, version ' SOFAgetVersion '. Copyright 2013-2022 Acoustics Research Institute (piotr@majdak.com).']); + if verbose >= 3 + disp(dispOutput); + end + if verbose >= 2 + disp(['This API implements SOFA version ' SOFAgetVersion('SOFA') '.']); + text=['Available SOFA Conventions: ' convs{1}]; + for ii=2:length(convs) + text=[text ', ' convs{ii}]; + end + disp(text); + disp(['SOFAdbPath (local HRTF database): ' SOFAdbPath('reset') ]); + disp(['SOFAdbURL (internet repository): ' SOFAdbURL('reset')]); + end +end + + + +% FIXME: I would check only if the URL is available in the function where it is +% needed. At the start it takes to long. Octaves urlread didn't know the TimeOut +% parameter. +%[~,stat]=urlread(SOFAdbURL); +%if ~stat, disp(' --> could not connect'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m new file mode 100644 index 0000000000000000000000000000000000000000..1209af8cf5faf7e0534699a604b91d2505222eb0 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAupdateDimensions.m @@ -0,0 +1,181 @@ +function Obj = SOFAupdateDimensions(Obj,varargin) +%SOFAupdateDimensions +% Obj = SOFAupdateDimensions(Obj, varargin) updates the dimensions in the SOFA +% structure +% +% Obj is a struct containing the data and meta. +% The dimension sizes are created as .API.X and updated corresponding to the +% conventions +% flag is 'nodata', 'all', or 'verbose'; default is 'all' +% set 'verbose' to 1 to obtain detailed information on the check. + +% #Author: Piotr Majdak +% #Author: Piotr Majdak: String support added (09.08.2014) +% #Author: Piotr Majdak: Verbose mode added (10.10.2020) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupdateDimensions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +definput.keyvals.Index=[]; +definput.keyvals.verbose=0; +definput.flags.type={'data','nodata'}; +[flags,kv]=SOFAarghelper({'Index'},definput,varargin); +v=kv.verbose; + +%% Get conventions with allowed dimensions +OC = SOFAgetConventions(Obj.GLOBAL_SOFAConventions,'a'); +if v, disp(['SOFA Convention: ' Obj.GLOBAL_SOFAConventions]); end + +%% Add dimensions if required +dims=fieldnames(SOFAdefinitions('dimensions')); +for ii=1:size(dims,1) + if ~isfield(Obj.API,dims{ii}), Obj.API.(dims{ii})=0; end +end + +%% Update dimension sizes from the variables having dominant dimensions sizes + % fix dimension sizes +Obj.API.I=1; +Obj.API.C=3; + % check all metadata variables for dominant dimension sizes +dims='renm'; +f=fieldnames(rmfield(OC.API.Dimensions,'Data')); +for ii=1:length(dims) + for jj=1:length(f) + dim=strfind(OC.API.Dimensions.(f{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.(f{jj}),dim(1)); + if (v), disp([upper(dims(ii)) ' set to ' num2str(size(Obj.(f{jj}),dim(1))) ' that is the #' num2str(dim(1)) ' dimension of ' f{jj}]); end + break; + end + end +end +% check all data variables +if flags.do_data + fd=fieldnames(OC.API.Dimensions.Data); + for ii=1:length(dims) + for jj=1:length(fd) + dim=strfind(OC.API.Dimensions.Data.(fd{jj}),dims(ii)); + if iscell(dim), dim=cell2mat(dim); end; + if ~isempty(dim) + Obj.API.(upper(dims(ii)))=size(Obj.Data.(fd{jj}),dim(1)); + if (v), disp([upper(dims(ii)) ' set to ' num2str(size(Obj.Data.(fd{jj}),dim(1))) ' that is the #' num2str(dim(1)) ' dimension of Data.' fd{jj}]); end + break; + end + end + end +end + +%% Update the dimensions of metadata variables +Smax=0; +X=rmfield(Obj,{'Data','API'}); +if isfield(X,'PRIVATE'), X=rmfield(X,'PRIVATE'); end +Xf=fieldnames(X); +for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions, Xf{ii}), % is a known variable + dim=OC.API.Dimensions.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.(Xf{ii})=dim; + if v, disp([Xf{ii} ': convention variable, used dimension: ' dim]); end; + end + else % is a user-defined variable + if ~isfield(Obj.API.Dimensions,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without dimension provided in API.Dimensions.']); + else + dim=Obj.API.Dimensions.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.(Xf{ii}))); + if isempty(dim), + error([Xf{ii} ': dimension does not match.']); + else + if v, disp([Xf{ii} ': user-defined variable, used dimension: ' dim]); end; + end + end + end + Smax=max(Smax,S); + end +end +%% Update the dimensions of data variables +if flags.do_data + Xf=fieldnames(Obj.Data); + for ii=1:length(Xf) + if isempty(strfind(Xf{ii},'_')), % is not an attribute... + if isfield(OC.API.Dimensions.Data, Xf{ii}), % is a known variable + dim=OC.API.Dimensions.Data.(Xf{ii}); + if ~iscell(dim), dim={dim}; end; + [dim,S]=checkdim(Obj,dim,sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension could not be matched.']); + else + Obj.API.Dimensions.Data.(Xf{ii})=dim; + if v, disp(['Data.' Xf{ii} ': convention variable, used dimension: ' dim]); end; + end + Smax=max(Smax,S); + else + if ~isfield(Obj.API.Dimensions.Data,Xf{ii}), + error([Xf{ii} ' seems to be a user-defined variable without a dimension.']); + else + dim=Obj.API.Dimensions.Data.(Xf{ii}); + [dim,S]=checkdim(Obj,{dim},sizecell(Obj.Data.(Xf{ii}))); + if isempty(dim), + error(['Data.' Xf{ii} ': dimension does not match.']); + else + if v, disp(['Data.' Xf{ii} ': user-defined variable, used dimension: ' dim]); end; + end + end + end + end + end +end +%% Update the size of the longest string +if Smax>0, + Obj.API.S=Smax; + if v, disp(['S set to ' num2str(Obj.API.S)]); end +else + if v, disp('S unused (set to 0)'); end +end + +%% Return the size of x. If x is a cell, return the size of the strings in x. +function s=sizecell(x,dim) +if iscell(x) + s=size(char(x)); + if size(x,1)~=s(1) s=[size(x) s(2)]; end % multidim cellarays: s = [celldim1, celldim2, ... , celldimN, stringdim] +else + s=size(x); +end + +%% Get the sizes of the dimension variables according the dimension variables in str +function vec=getdim(Obj,str) + vec=arrayfun(@(f)(Obj.(f)),upper(str)); + +%% dims is a cell array with allowed dimensions. +% S is the size of the string dimension. S=0 when S does not exist +% dimA is a vector with the actual dimensions. +% dim is a string with the matching dimension +function [dim,S]=checkdim(Obj,dims,dimA) +dim=[]; S=0; +for jj=1:length(dims) + dimS=dims{jj}; + if length(dimS)==1, dimS=[dimS 'I']; end; % 1D required, but Matlab is always 2D at least. + dimR=getdim(Obj.API,dimS); + if length(dimA)==length(dimR), % the same size? + if ~isempty(strfind(dimS,'S')) + Sidx=strfind(dimS,'S'); + S=max(S,dimA(Sidx)); + dimR(Sidx)=dimA(Sidx); % string dim are always correct + end + if dimA==dimR, dim=upper(dims{jj}); break; end; % found! + elseif length(dimA)<length(dimR) % extend the size? + if [dimA ones(1,length(dimR)-length(dimA))]==dimR, dim=upper(dims{jj}); break; end; % found! + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m new file mode 100644 index 0000000000000000000000000000000000000000..e1acb20158d187b75073a274e0486ee86444ab10 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/SOFAupgradeConventions.m @@ -0,0 +1,174 @@ +function [Obj,modified] = SOFAupgradeConventions(Obj) +%SOFAcompatibility +% [Obj,modified] = SOFAupgradeConventions(Obj) upgrades the Obj to the next higher +% version if required. MODIFIED is 1 when an upgrade was required. +% In order to obtain the most recent version, SOFAupgradeConventions +% should be processed recursively until MODIFIED is 0. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function SOFAupgradeConventions +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +modified=0; + +%% Upgrade specific to a SOFA version + +switch Obj.GLOBAL_Version, + case '0.3' + modified=1; + % in SOFA 0.3, only SimpleFreeFieldHRIR 0.1 was supported. + % Updating SimpleFreeFieldHRIR 0.1 to 0.2 + Obj.GLOBAL_Version='0.4'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + Obj.GLOBAL_TimeCreated=Obj.GLOBAL_DatabaseTimeCreated; + Obj.GLOBAL_TimeModified=Obj.GLOBAL_DatabaseTimeModified; + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.3'); + % remove dimensional variables and not used variables/attributes + dims={'I','R','E','N','M','C','Q','SourceView',... + 'SourceUp','GLOBAL_DatabaseTimeCreated','GLOBAL_DatabaseTimeModified'}; + f=fieldnames(Obj); + for ii=1:length(dims) + for jj=1:length(f) + if strcmp(f{jj},dims{ii}), + Obj=rmfield(Obj,f{jj}); % remove variable or attribute + if isempty(strfind(f{jj},'_')), + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,f{jj}); % remove dimension + end + elseif strcmp(f{jj}(1:min(length(dims{ii})+1,length(f{jj}))),[dims{ii} '_']) + Obj=rmfield(Obj,f{jj}); % remove attributes of that variable + end + end + end + warning('SOFA:upgrade','SOFA 0.3 upgraded to 0.4. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.4' + % in SOFA 0.4, only SimpleFreeFieldHRIR might need upgrade + if strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR') + switch Obj.GLOBAL_SOFAConventionsVersion + case '0.2' + % Upgrade from SimpleFreeFieldHRIR 0.2 to 0.3 + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SimpleFreeFieldHRIR 0.2'); + % Create temp SourcePosition + azi=bsxfun(@times,Obj.ListenerRotation(:,1),ones(size(Obj.ListenerPosition,1),1)); + ele=bsxfun(@times,Obj.ListenerRotation(:,2),ones(size(Obj.ListenerPosition,1),1)); + r=bsxfun(@times,Obj.ListenerPosition(:,1),ones(size(Obj.ListenerRotation,1),1)); + % Copy ListenerPosition + Obj.ListenerPosition=Obj.SourcePosition; + % Overwrite SourcePosition + Obj.SourcePosition=[azi ele r]; + Obj.SourcePosition_Type='spherical'; + Obj.SourcePosition_Units='degree, degree, meter'; + % Mirror the ListenerView and correct ListenerUp + Obj.ListenerView=-Obj.ListenerView; + Obj.ListenerUp=[0 0 1]; + % Remove irrelevant fields + if isfield(Obj,'SourceView'); Obj=rmfield(Obj,'SourceView'); end + if isfield(Obj,'SourceView_Type'); Obj=rmfield(Obj,'SourceView_Type'); end + if isfield(Obj,'SourceView_Units'); Obj=rmfield(Obj,'SourceView_Units'); end + if isfield(Obj,'SourceUp'); Obj=rmfield(Obj,'SourceUp'); end + if isfield(Obj,'SourceUp_Type'); Obj=rmfield(Obj,'SourceUp_Type'); end + if isfield(Obj,'SourceUp_Units'); Obj=rmfield(Obj,'SourceUp_Units'); end + Obj=rmfield(Obj,'ListenerRotation'); + Obj=rmfield(Obj,'ListenerRotation_Type'); + Obj=rmfield(Obj,'ListenerRotation_Units'); + Obj.API.Dimensions=rmfield(Obj.API.Dimensions,'ListenerRotation'); + Obj.GLOBAL_SOFAConventionsVersion='0.3'; + end + end + modified=1; + Obj.GLOBAL_Version='0.5'; + warning('SOFA:upgrade','SOFA 0.4 upgraded to 0.5. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.5' + % Upgrade from 0.5 to 0.6 + Obj.GLOBAL_DateCreated=Obj.GLOBAL_TimeCreated; + Obj=rmfield(Obj,'GLOBAL_TimeCreated'); + Obj.GLOBAL_DateModified=Obj.GLOBAL_TimeModified; + Obj=rmfield(Obj,'GLOBAL_TimeModified'); + Obj.GLOBAL_Origin=Obj.GLOBAL_Source; + Obj=rmfield(Obj,'GLOBAL_Source'); + if isfield(Obj,'ListenerView') && ~isfield(Obj,'ListenerView_Type') + Obj.ListenerView_Type = 'cartesian'; + Obj.ListenerView_Units = 'meter'; + end + if isfield(Obj,'ReceiverView') && ~isfield(Obj,'ReceiverView_Type') + Obj.ReceiverView_Type = 'cartesian'; + Obj.ReceiverView_Units = 'meter'; + end + if isfield(Obj,'GLOBAL_SubjectID'), + Obj.GLOBAL_ListenerShortName=Obj.GLOBAL_SubjectID; % rename SubjectID to ListenerShortName + Obj=rmfield(Obj,'GLOBAL_SubjectID'); + end + switch Obj.GLOBAL_SOFAConventions + case {'SimpleFreeFieldHRIR', 'SimpleFreeFieldTF'} + Obj.GLOBAL_SOFAConventionsVersion='0.4'; + case {'GeneralFIR', 'GeneralTF', 'SingleRoomDRIR'} + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + end + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.5'); + Obj.GLOBAL_Version='0.6'; + modified=1; + warning('SOFA:upgrade','SOFA 0.5 upgraded to 0.6. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + case '0.6' + X=SOFAgetConventions(Obj.GLOBAL_SOFAConventions); + if ~isempty(X), + Obj.GLOBAL_History=SOFAappendText(Obj,'GLOBAL_History','Upgraded from SOFA 0.6'); + Obj.GLOBAL_Version='1.0'; + Obj.GLOBAL_SOFAConventionsVersion = X.GLOBAL_SOFAConventionsVersion; + % replace aliases by correct unit names + U=SOFAdefinitions('units'); + Uf=fieldnames(U); + f=fieldnames(Obj); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.(f{jj})=regexprep(Obj.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + f=fieldnames(Obj.Data); + for jj=1:length(f) + if length(f{jj}) > 6 + if strcmp(f{jj}(end-5:end),'_Units') + for ii=1:length(Uf) % _Units found, check for alias + Obj.Data.(f{jj})=regexprep(Obj.Data.(f{jj}), U.(Uf{ii}), Uf{ii}, 'ignorecase'); + end + end + end + end + modified=1; + warning('SOFA:upgrade','SOFA 0.6 upgraded to 1.0. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + else + warning('SOFA:upgrade','Unknown conventions'); + end +end + +%% Upgrade specific to conventions +if ~modified + switch Obj.GLOBAL_SOFAConventions + case 'MultiSpeakerBRIR' + if strcmp(Obj.GLOBAL_SOFAConventionsVersion,'0.1'); + % upgrade to 0.2 + Obj.GLOBAL_DataType='FIRE'; + Obj.GLOBAL_SOFAConventionsVersion='0.2'; + %Obj.Data.Delay = + if strcmp(Obj.API.Dimensions.Data.Delay,'IR') + Obj.API.Dimensions.Data.Delay='IRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + if strcmp(Obj.API.Dimensions.Data.Delay,'MR') + Obj.API.Dimensions.Data.Delay='MRE'; + Obj.Data.Delay=repmat(Obj.Data.Delay,[1 1 size(Obj.EmitterPosition,1)]); + end + modified=1; + warning('SOFA:upgrade','Conventions MultiSpeakerBRIR 0.1 upgraded to 0.2. Use warning(''off'',''SOFA:upgrade''); to switch off this warning. '); + end + end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..af56fe7d165a9e5a2b38223ad23d470427882e0b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldDirectivityTF_1.0.csv @@ -0,0 +1,58 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldDirectivityTF rm attribute This conventions stores directivities of acoustic sources (instruments, loudspeakers, singers, talkers, etc) in the frequency domain for multiple musical notes in free field. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:RoomType free field m attribute The room information can be arbitrary, but the spatial setup assumes free field. +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment m attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data +GLOBAL:Musician attribute Narrative description of the musician such as position, behavior, or personal data if not data-protected, e.g., 'Christiane Schmidt sitting on the chair', or 'artificial excitation by R2D2'. +GLOBAL:Description attribute Narrative description of a measurement. For musical instruments/singers, the note (C1, D1, etc) or the dynamic (pp., ff., etc), or the string played, the playing style (pizzicato, legato, etc.), or the type of excitation (e.g., hit location of a cymbal). For loudspeakers, the system and driver units. +GLOBAL:SourceType m attribute Narrative description of the acoustic source, e.g., 'Violin', 'Female singer', or '2-way loudspeaker' +GLOBAL:SourceManufacturer m attribute Narrative description of the manufacturer of the source, e.g., 'Stradivari, Lady Blunt, 1721' or 'LoudspeakerCompany' +ListenerPosition [0 0 0] m IC, MC double Position of the microphone array during the measurements. +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double Orientation of the microphone array +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +ListenerUp [0 0 1] m IC, MC double Up vector of the microphone array +ReceiverPosition [0 0 1] m IC, RC, RCM double Positions of the microphones during the measurements (relative to the Listener) +ReceiverPosition:Type spherical m attribute +ReceiverPosition:Units degree, degree, metre m attribute +SourcePosition [0 0 0] m IC, MC double Position of the acoustic source (instrument) +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourcePosition:Reference m attribute Narrative description of the spatial reference of the source position, e.g., for the trumpet, 'The bell'. Mandatory in order to provide a reference across different instruments +SourceView [1 0 0] m IC, MC double Orientation of the acoustic source (instrument) +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +SourceView:Reference m attribute Narrative description of the spatial reference of the source view, e.g., for the trumpet, 'Viewing direction of the bell'. Mandatory in order to provide a reference across different instruments +SourceUp [0 0 1] m IC, MC double Up vector of the acoustic source (instrument) +SourceUp:Reference m attribute Narrative description of the spatial reference of the source up, e.g., for the trumpet, 'Along the keys, keys up'. Mandatory in order to provide a reference across different instruments +EmitterPosition [0 0 0] m IC, MC double A more detailed structure of the Source. In a simple settings, a single Emitter is considered that is collocated with the source. +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterDescription {''} IS, MS string A more detailed structure of the source. In a simple setting, a single Emitter is considered that is collocated with the source. In a more complicated setting, this may be the strings of a violin or the units of a loudspeaker. +MIDINote 0 I, M double Defines the note played by the source during the measurement. The note is specified a MIDI note by the [https://www.midi.org/specifications-old/item/the-midi-1-0-specification MIDI specifications, version 1.0]. Not mandatory, but recommended for tonal instruments. +Description {''} MS string This variable is used when the description varies with M. +SourceTuningFrequency 440 I, M double Frequency (in hertz) to which a musical instrument is tuned to corresponding to the note A4 (MIDINote=69). Recommended for tonal instruments. +Data.Real 0 m mrn double Real part of the complex spectrum. The default value 0 indicates that all data fields are initialized with zero values. +Data.Imag 0 m MRN double Imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Units used for N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..1b837bddbb08f4a135e991845c07e9204482268d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRIR_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldHRIR rm attribute An extension of SimpleFreeFieldHRIR in order to consider more complex data sets described in spatially continuous representation. Each HRTF direction corresponds to an emitter, and a consistent measurement for a single listener and all directions is described by a set of the emitter positions surrounding the listener. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR-E rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Source position is assumed to be the ListenerPosition in order to reflect Emitters surrounding the Listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double Radius in 'spherical harmonics', Position in 'cartesian' and 'spherical' +EmitterPosition:Type spherical harmonics m attribute Can be 'spherical harmonics', 'cartesian', or 'spherical' +EmitterPosition:Units degree, degree, metre m attribute +GLOBAL:DatabaseName m attribute Name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.IR [0 0] m mrne double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..3e20f7a46d5f6e419987efcf2d08763a8733d38d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/FreeFieldHRTF_1.0.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions FreeFieldHRTF rm attribute This conventions is for HRTFs created under conditions where room information is irrelevant and stored as SH coefficients +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF-E rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Source position is assumed to be the ListenerPosition in order to reflect Emitters surrounding the Listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double Radius in 'spherical harmonics', Position in 'cartesian' and 'spherical' +EmitterPosition:Type spherical harmonics m attribute Can be 'spherical harmonics', 'cartesian', or 'spherical' +EmitterPosition:Units degree, degree, metre m attribute +GLOBAL:DatabaseName m attribute Name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.Real [0 0] m mrne double +Data.Imag [0 0] m MRNE double +N 0 m N double +N:LongName frequency attribute +N:Units hertz m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..9bc63d5252c59efd77d597f5042a8f3b0ffa09d1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR-E_2.0.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR-E rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR-E rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, EC, ECM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mrne double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR.csv new file mode 100644 index 0000000000000000000000000000000000000000..a3d46ef46e288224905e221d7f5381c0f6c431d2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mRn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..c767c77a815dd871c45098f2e851e17c424cebcf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIRE_1.0.csv @@ -0,0 +1,37 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIRE rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mREn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRE, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..a3d46ef46e288224905e221d7f5381c0f6c431d2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_1.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mRn double Impulse responses +Data.SamplingRate 48000 m I double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..9845f4b14ded04145b7479f021a2c7a88fc52db2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralFIR_2.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralFIR rm attribute This conventions stores IRs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..e83701b0df861875f4bc6589efaa24a776119742 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralSOS_1.0.csv @@ -0,0 +1,40 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2 rm attribute +GLOBAL:SOFAConventions GeneralSOS rm attribute This conventions follows GeneralFIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0], [3 1 2]); m mrn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I, M double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv new file mode 100644 index 0000000000000000000000000000000000000000..4092d8d9bccc3064f3bc972d65bbdb1206bee68f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralString_0.2.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralString rm attribute Conventions for testing the string support +GLOBAL:SOFAConventionsVersion 0.2 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType String rm attribute We store strings here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +String2 {'' ''} m MRS string +String2:Description 2-D string m attribute +String2:Units latin1 m attribute +Data.String1 {''} m MS string +Data.String1:Description 1-D string m attribute +Data.String1:Units latin1 m attribute +Data.String2 {'' ''} m MRS string +Data.String2:Description 2-D string m attribute +Data.String2:Units latin1 m attribute +Data.Double [0 0] m mRn double +Data.Double:Units double m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..50fba44919116cacc932c6dde0f1b27f266eb241 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF-E_1.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions GeneralTF-E rm attribute This conventions stores TFs depending in the Emiiter for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralTF +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType TF-E rm attribute We store frequency-dependent data depending on the emitter here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m IC, EC, ECM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mrne double The real part of the complex spectrum +Data.Imag 0 m MRNE double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..3a14a5de1231813d3a5bab18f38ebb029084e067 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_1.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralTF rm attribute This conventions stores TFs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralFIR. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mRn double The real part of the complex spectrum +Data.Imag 0 m MRN double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..e30250d612db4a35a39b8082a385bc29190c5ae3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/GeneralTF_2.0.csv @@ -0,0 +1,38 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions GeneralTF rm attribute This conventions stores TFs for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined. This convention is based on GeneralFIR. +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType TF rm attribute We store frequency-dependent data here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m IC, RC, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double In order to store different directions/positions around the listener, SourcePosition is assumed to vary +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.Real 0 m mrn double The real part of the complex spectrum +Data.Imag 0 m MRN double The imaginary part of the complex spectrum +N 0 m N double Frequency values +N:LongName frequency m attribute +N:Units hertz m attribute Unit of the values given in N diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..73696de08abd826f5eb3da8d460aef2845c1618f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/General_1.0.csv @@ -0,0 +1,61 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions General rm attribute This conventions is for general purposes, i.e., only the mandatory, SOFA general metadata are pre-defined +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR m attribute The datatype can be arbitrary +GLOBAL:RoomType free field m attribute The room information can be arbitrary +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] IC, MC double +ListenerUp [0 0 1] IC, MC double +ListenerView:Type cartesian attribute +ListenerView:Units metre attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] IC, MC double +SourceUp [0 0 1] IC, MC double +SourceView:Type cartesian attribute +SourceView:Units metre attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterPosition [0 0 0] m IC, ECI, ECM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmiiterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv new file mode 100644 index 0000000000000000000000000000000000000000..bb45db38ab7773c59b5361ca94cdb43d1b8e5122 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/MultiSpeakerBRIR_0.3.csv @@ -0,0 +1,48 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions MultiSpeakerBRIR rm attribute This convention is for BRIRs recorded in reverberant conditions from multiple loudspeaker sources at a number of listener orientations. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIRE rm attribute We use FIR datatype which in addition depends on Emitters (E) +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double Each speaker is represented as an emitter. Use EmitterPosition to represent the position of a particular speaker. Size of EmitterPosition determines E +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:RoomDescription attribute narrative description of the room +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +EmitterUp [0 0 1] ECI, ECM double When EmitterUp provided, EmitterView must be provided as well +EmitterView [1 0 0] ECI, ECM double When EmitterView provided, EmitterUp must be provided as well +EmitterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR [1 1] m mREn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IRE, MRE double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..3307cfcbbcc50ae300ca91e98b73cd44e1a9a8d4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRIR_1.0.csv @@ -0,0 +1,47 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRIR rm attribute This convention set is for HRIRs recorded under free-field conditions or other IRs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double +SourceUp [0 0 1] IC, MC double +SourceView [1 0 0] IC, MC double +SourceView:Type cartesian attribute +SourceView:Units metre attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..9aecc490b9896ddbc6cab3a90a8074a36721e031 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRSOS_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRSOS rm attribute This convention set follows SimpleFreeFieldHRIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0; 0 0 0 1 0 0], [3 1 2]); m mRn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I, M double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..327c97f1a3379634d099054873a9ca05fa79c9d7 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldHRTF_2.0.csv @@ -0,0 +1,44 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldHRTF rm attribute This conventions is for HRTFs created under conditions where room information is irrelevant +GLOBAL:SOFAConventionsVersion 2.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType TF rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ListenerShortName m attribute ID of the subject from the database +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.Real [0 0] m mRn double +Data.Imag [0 0] m MRN double +N 0 m N double +N:LongName frequency attribute +N:Units hertz m attribute diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..f576df1d3caaf1fa072d279d150326ea5798ac27 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleFreeFieldSOS_1.0.csv @@ -0,0 +1,43 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SimpleFreeFieldSOS rm attribute This convention set follows SimpleFreeFieldHRIR but the data is stored as second-order section (SOS) coefficients. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment attribute +GLOBAL:DataType SOS rm attribute Filters described as second-order section (SOS) coefficients +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 1] m IC, MC double Source position is assumed to vary for different directions/positions around the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute name of the database to which these data belong +GLOBAL:ListenerShortName m attribute ID of the subject from the database +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +Data.SOS permute([0 0 0 1 0 0; 0 0 0 1 0 0], [3 1 2]); m mRn double Filter coefficients as SOS coefficients. +Data.SamplingRate 48000 m I double Sampling rate of the coefficients in Data.SOS and the delay in Data.Delay +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double Broadband delay (in samples resulting from SamplingRate) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..e1845bc7eb504e288e26cc3d6070e282ce327143 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SimpleHeadphoneIR_1.0.csv @@ -0,0 +1,51 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SimpleHeadphoneIR rm attribute Conventions for IRs with a 1-to-1 correspondence between emitter and receiver. The main application for this convention is to store headphone IRs recorded for each emitter and each ear. +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute We will store IRs here +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType free field m attribute Room type is not relevant here +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0.09 0; 0 -0.09 0] m rCI, rCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double Default: Headphones are located at the position of the listener +SourcePosition:Type spherical m attribute +SourcePosition:Units degree, degree, metre m attribute +EmitterPosition [0 0.09 0; 0 -0.09 0] m eCI, eCM double Default: Reflects the correspondence of each emitter to each receiver +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +Data.IR [0 0] m mRn double +Data.SamplingRate 48000 m I, M double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0 0] m IR, MR double +GLOBAL:DatabaseName m attribute Correspondence to a database +GLOBAL:ListenerShortName m attribute Correspondence to a subject from the database +GLOBAL:ListenerDescription m attribute Narrative description of the listener (or mannequin) +GLOBAL:SourceDescription m attribute Narrative description of the headphones +GLOBAL:SourceManufacturer m attribute Name of the headphones manufacturer +SourceManufacturer {''} MS string Optional M-dependent version of the attribute SourceManufucturer +GLOBAL:SourceModel m attribute Name of the headphone model. Must uniquely describe the headphones of the manufacturer +SourceModel {''} MS string Optional M-dependent version of the attribute SourceModel +GLOBAL:SourceURI m attribute URI of the headphone specifications +GLOBAL:ReceiverDescription m attribute Narrative description of the microphones +ReceiverDescriptions {''} MS string R-dependent version of the attribute ReceiverDescription +GLOBAL:EmitterDescription m attribute Narrative description of the headphone drivers +EmitterDescriptions {''} MS string E-dependent version of the attribute EmitterDescription +MeasurementDate 0 M double Optional M-dependent date and time of the measurement diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv new file mode 100644 index 0000000000000000000000000000000000000000..0658a79a697550a8a25f646859395b24383df7a3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomDRIR_0.3.csv @@ -0,0 +1,47 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 1.0 rm attribute +GLOBAL:SOFAConventions SingleRoomDRIR rm attribute This convention stores arbitrary number of receivers while providing an information about the room. The main application is to store DRIRs for a single room. +GLOBAL:SOFAConventionsVersion 0.3 rm attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Comment m attribute +GLOBAL:DataType FIR rm attribute +GLOBAL:History attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:Organization m attribute +GLOBAL:References attribute +GLOBAL:RoomType reverberant m attribute +GLOBAL:Origin attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:Title m attribute +ListenerPosition [0 0 0] m IC, MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ReceiverPosition [0 0 0] m RCI, RCM double +ReceiverPosition:Type cartesian m attribute +ReceiverPosition:Units metre m attribute +SourcePosition [0 0 0] m IC, MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type cartesian m attribute +EmitterPosition:Units metre m attribute +GLOBAL:DatabaseName m attribute +GLOBAL:RoomDescription m attribute +ListenerUp [0 0 1] m IC, MC double +ListenerView [1 0 0] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +SourceUp [0 0 1] m IC, MC double +SourceView [-1 0 0] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +Data.IR [0] m mrn double +Data.SamplingRate 48000 m I double +Data.SamplingRate:Units hertz m attribute +Data.Delay [0] m IR, MR double diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..7f83b04c5db8a3e21ee5474a5f3b96ccf39e6294 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomMIMOSRIR_1.0.csv @@ -0,0 +1,77 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SingleRoomMIMOSRIR rm attribute Single-room multiple-input multiple-output spatial room impulse responses, depending on Emitters +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR-E rm attribute Shall be FIR-E +GLOBAL:RoomType shoebox m attribute Shall be 'shoebox' or 'dae' +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data. +GLOBAL:RoomShortName attribute Short name of the Room +GLOBAL:RoomDescription attribute Informal verbal description of the room +GLOBAL:RoomLocation attribute Location of the room +GLOBAL:RoomGeometry attribute URI to a file describing the room geometry. +RoomTemperature 0 I, M double Temperature during measurements +RoomTemperature:Units kelvin attribute Units of the room temperature +RoomVolume 0 I, M double Volume of the room +RoomVolume:Units cubic metre attribute Units of the room volume +RoomCornerA [0 0 0] IC, MC double +RoomCornerB [1 2 3] IC, MC double +RoomCorners 0 II double The value of this attribute is to be ignored. It only exist to for RoomCorners:Type and RoomCorners:Units +RoomCorners:Type cartesian attribute +RoomCorners:Units metre attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double +ListenerUp [0 0 1] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverDescriptions {''} RS string R-dependent version of the attribute ReceiverDescription +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type spherical m attribute Can be of any type enabling both spatially discrete and spatially continuous representations. +ReceiverPosition:Units degree, degree, metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] m IC, MC double +SourceUp [0 0 1] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterDescriptions {''} ES string E-dependent version of the attribute EmitterDescription +EmitterPosition [0 0 0] m IC, ECI, ECM double Can be of any type enabling both spatially discrete and spatially continuous representations. +EmitterPosition:Type spherical m attribute +EmitterPosition:Units degree, degree, metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmitterView:Type cartesian attribute +EmitterView:Units metre attribute +Data.IR 0 m mrne double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IRI, MRI, MRE double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv new file mode 100644 index 0000000000000000000000000000000000000000..08abef00675f9c50d4aac3c0a552cfb67c2f1cbe --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/conventions/SingleRoomSRIR_1.0.csv @@ -0,0 +1,77 @@ +Name Default Flags Dimensions Type Comment +GLOBAL:Conventions SOFA rm attribute +GLOBAL:Version 2.0 rm attribute +GLOBAL:SOFAConventions SingleRoomSRIR rm attribute For measuring SRIRs in a single room with a single excitation source (e.g., a loudspeaker) and a listener containing an arbitrary number of omnidirectional receivers (e.g., a microphone array). +GLOBAL:SOFAConventionsVersion 1.0 rm attribute +GLOBAL:DataType FIR rm attribute Shall be FIR +GLOBAL:RoomType shoebox m attribute Shall be 'shoebox' or 'dae' +GLOBAL:Title m attribute +GLOBAL:DateCreated m attribute +GLOBAL:DateModified m attribute +GLOBAL:APIName rm attribute +GLOBAL:APIVersion rm attribute +GLOBAL:AuthorContact m attribute +GLOBAL:Organization m attribute +GLOBAL:License No license provided, ask the author for permission m attribute +GLOBAL:ApplicationName attribute +GLOBAL:ApplicationVersion attribute +GLOBAL:Comment attribute +GLOBAL:History attribute +GLOBAL:References attribute +GLOBAL:Origin attribute +GLOBAL:DatabaseName m attribute Name of the database. Used for classification of the data. +GLOBAL:RoomShortName attribute Short name of the Room +GLOBAL:RoomDescription attribute Informal verbal description of the room +GLOBAL:RoomLocation attribute Location of the room +GLOBAL:RoomGeometry attribute URI to a file describing the room geometry. +RoomTemperature 0 I, M double Temperature during measurements +RoomTemperature:Units kelvin attribute Units of the room temperature +RoomVolume 0 I, M double Volume of the room +RoomVolume:Units cubic metre attribute Units of the room volume +RoomCornerA [0 0 0] IC, MC double +RoomCornerB [1 2 3] IC, MC double +RoomCorners 0 II double The value of this attribute is to be ignored. It only exist to for RoomCorners:Type and RoomCorners:Units +RoomCorners:Type cartesian attribute +RoomCorners:Units metre attribute +GLOBAL:ListenerShortName attribute +GLOBAL:ListenerDescription attribute +ListenerPosition [0 0 0] m MC double +ListenerPosition:Type cartesian m attribute +ListenerPosition:Units metre m attribute +ListenerView [1 0 0] m IC, MC double +ListenerUp [0 0 1] m IC, MC double +ListenerView:Type cartesian m attribute +ListenerView:Units metre m attribute +GLOBAL:ReceiverShortName attribute +GLOBAL:ReceiverDescription attribute +ReceiverDescriptions {''} RS string R-dependent version of the attribute ReceiverDescription +ReceiverPosition [0 0 0] m IC, RCI, RCM double +ReceiverPosition:Type spherical m attribute Can be of any type enabling both spatially discrete and spatially continuous representations. +ReceiverPosition:Units degree, degree, metre m attribute +ReceiverView [1 0 0] RCI, RCM double +ReceiverUp [0 0 1] RCI, RCM double +ReceiverView:Type cartesian attribute +ReceiverView:Units metre attribute +GLOBAL:SourceShortName attribute +GLOBAL:SourceDescription attribute +SourcePosition [0 0 1] m MC double +SourcePosition:Type cartesian m attribute +SourcePosition:Units metre m attribute +SourceView [1 0 0] m IC, MC double +SourceUp [0 0 1] m IC, MC double +SourceView:Type cartesian m attribute +SourceView:Units metre m attribute +GLOBAL:EmitterShortName attribute +GLOBAL:EmitterDescription attribute +EmitterDescriptions {''} ES string E-dependent version of the attribute EmitterDescription +EmitterPosition [0 0 0] m eCI, eCM double +EmitterPosition:Type spherical m attribute Shall be 'cartesian' or 'spherical', restricting to spatially discrete emitters. +EmitterPosition:Units degree, degree, metre m attribute +EmitterView [1 0 0] ECI, ECM double +EmitterUp [0 0 1] ECI, ECM double +EmitterView:Type cartesian attribute Shall be 'cartesian' or 'spherical', restricting to spatially discrete emitters. +EmitterView:Units metre attribute +Data.IR 0 m mrn double Impulse responses +Data.SamplingRate 48000 m I, M double Sampling rate of the samples in Data.IR and Data.Delay +Data.SamplingRate:Units hertz m attribute Unit of the sampling rate +Data.Delay 0 m IR, MR double Additional delay of each IR (in samples) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..3d885d7c8b34b5aa62ded535f12efa619d8c6f97 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertARI2SOFA.m @@ -0,0 +1,49 @@ +function Obj=SOFAconvertARI2SOFA(hM,meta,stimPar) +% OBJ=SOFAconvertARI2SOFA(hM,meta,stimPar) converts the HRTFs described in hM, meta, and +% stimPar (see ARI HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(hM,1); % hM is [N M R], data.IR must be [M R N] +Obj.Data.SamplingRate = stimPar.SamplingRate; + +%% Fill with attributes +if isfield(stimPar, 'SubjectID'), Obj.GLOBAL_ListenerShortName = stimPar.SubjectID; end +if isfield(stimPar,'Application') + if isfield(stimPar.Application,'Name'), Obj.GLOBAL_ApplicationName = stimPar.Application.Name; end + if isfield(stimPar.Application,'Version'), Obj.GLOBAL_ApplicationVersion = stimPar.Application.Version; end +end + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.2 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) zeros(size(hM,2),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [meta.pos(1:size(hM,2),1) meta.pos(1:size(hM,2),2) 1.2*ones(size(hM,2),1)]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with some additional data +Obj.GLOBAL_History='Converted from the ARI format'; +if size(meta.pos,2)>2, Obj=SOFAaddVariable(Obj,'MeasurementSourceAudioChannel','M',meta.pos(1:size(hM,2),3)); end +if isfield(meta,'lat'), Obj=SOFAaddVariable(Obj,'MeasurementAudioLatency','MR',meta.lat); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8e8eee834f3eecbf5cf0586460bce52910c01df4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertBTDEI2SOFA.m @@ -0,0 +1,83 @@ +function Obj = SOFAconvertBTDEI2SOFA(BTDEI) +% OBJ=SOFAconvertBTDEI2SOFA(BTDEI) converts the HRTFs described in BT-DEI +% to a SOFA object. +% +% BTDEI format is used by Michele Geronazzo, University of Padova. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +% get empty object (the flag 'm' provides the mandatory fields only) +Obj=SOFAgetConventions('SimpleHeadphoneIR','m'); + +Obj.GLOBAL_Title = 'HPIR'; +Obj.GLOBAL_DatabaseName = BTDEI.specs.Database; + +Obj.GLOBAL_History = 'Converted from the BT-DEI format'; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HpTFs from DEI - University of Padova'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_AuthorContact = 'geronazzo@dei.unipd.it'; +Obj.GLOBAL_References = ['M. Geronazzo, F. Granza, S. Spagnol, F. Avanzini. ', ... + 'A Standardized Repository of Head-Related and Headphone Impulse Response Data ', ... + 'In 134th Convention of the Audio Engineering Society, May 2013.']; +Obj.GLOBAL_Organization = 'Department of Information Engineering, University of Padova'; +Obj.GLOBAL_Comment = ''; + +% copy the data + +% Emitter - Source +Obj.GLOBAL_SourceDescription = [BTDEI.hp.Id ' - ' BTDEI.hp.Producer ' ' BTDEI.hp.Model]; +Obj.GLOBAL_SourceManufacturer = BTDEI.hp.Producer; +Obj.GLOBAL_SourceModel = BTDEI.hp.Model; +%Obj.GLOBAL_SourceURI = BTDEI.hp.Uri; +% Receiver - Listener +Obj.GLOBAL_SubjectID = BTDEI.specs.SubjectId; +Obj.GLOBAL_ListenerDescription = BTDEI.sbjType; +Obj.GLOBAL_ReceiverDescription = BTDEI.specs.MicrophonePosition; % qualitative data e.g. blocked ear canal, open ear canal, at the eardrum + + +Obj.ListenerPosition = [0 0 0]; +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 0]; +Obj.SourcePosition = [0 0 0]; +Obj.EmitterPosition = [0 0.09 0; 0 -0.09 0]; + +%% Fill data with data +Obj.Data.SamplingRate = BTDEI.specs.SampleRate; % Sampling rate + +% calculate the effective size of the data matrix +M = length(BTDEI.data); % number of repositionings +R = size(BTDEI.data(1).HpIR,2); % number of channels (stereo) + +len_vec = zeros(M,1); +for ii=1:M + len_vec(ii)= length(BTDEI.data(ii).HpIR); +end +N = max(len_vec); + +Obj.API.M=M; +Obj.API.R=R; +Obj.API.N=N; + +% store IR data +Obj.Data.IR = NaN(M,R,N); % data.IR must be [M R N] +for aa=1:M + HpIR = [BTDEI.data(aa).HpIR; zeros((N-length(BTDEI.data(aa).HpIR)),2)]; + Obj.Data.IR(aa,1,:)= HpIR(:,1)'; + Obj.Data.IR(aa,2,:)= HpIR(:,2)'; +end + + +% update dimensions +Obj = SOFAupdateDimensions(Obj); +end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..1d8c818b355c939b002b11fbefa3cf58f980ade8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertCIPIC2SOFA.m @@ -0,0 +1,61 @@ +function Obj=SOFAconvertCIPIC2SOFA(CIPIC) +% Obj=SOFAconvertCIPIC2SOFA(CIPIC) converts the HRTFs described in the structure CIPIC +% (see CIPIC HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +ida=round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1)); +lat=lat1(ida); + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,size(CIPIC.hrir_l,3)); % data.IR must be [M R N] +Obj.Data.SamplingRate = 44100; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=CIPIC.hrir_l(aa,ee,:); + Obj.Data.IR(ii,2,:)=CIPIC.hrir_r(aa,ee,:); + [azi,ele]=hor2sph(-lat(ii),pol(ii)); + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = CIPIC.name; +Obj.GLOBAL_History = 'Converted from the CIPIC file format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; +% SimpleFreeFieldHRIR 0.3 and 0.4 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..efec2f5daff8a42730eabed68a4d86141b575bbd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertFHK2SOFA.m @@ -0,0 +1,71 @@ +function Obj=SOFAconvertFHK2SOFA(miroObj) +% OBJ=SOFAconvertFHK2SOFA(miroObj) converts the HRTFs described in miroObj +% to SOFA. miroObj is the miro object saved at the Fach-Hochschule Köln +% provided by Benjamin Bernschütz. +% Reference to the source format: http://www.audiogroup.web.fh-koeln.de/ku100hrir.html +% Reference to the source coordinate system: [1] http://code.google.com/p/sofia-toolbox/wiki/COORDINATES + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% if isoctave, +if exist('OCTAVE_VERSION','builtin') ~= 0 + error(['Octave is not able to convert FHK to SOFA, use Matlab instead.']); +end + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = miroObj.irChOne; % irChOne is [N M] +Obj.Data.IR(:,:,2) = miroObj.irChTwo; +Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +% Obj.GLOBAL_APIName +% Obj.GLOBAL_ApplicationName +% Obj.GLOBAL_ApplicationVersion +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = miroObj.context; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Fachhochschule Köln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_References = 'Bernschütz, B. (2013). "A Spherical Far Field HRIR/HRTF Compilation of the Neumann KU 100", proceedings of the AIA/DAGA, Meran, Italy'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Origin = 'http://www.audiogroup.web.fh-koeln.de/ku100hrir.html'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='FHK'; +Obj.GLOBAL_Title = 'HRTF'; + +%% Fill the mandatory variables +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + % From [1]: All angles are in RAD. + % AZ denotes the azimutal angle in a range of (0-2pi(. Whereas AZ=0 is defined to be the front direction and AZ=pi to be the rear direction. + % EL denotes the elevation angle in a range of (0-pi). EL=0 points upwards, EL=pi/2 points to the horizontal plane and EL=pi points downwards. + % r is the radius in meters (if needed/specified). +Obj.SourcePosition = [... + rad2deg(miroObj.azimuth') ... % miroObj.azimuth is AZ + 90-rad2deg(miroObj.elevation') ... % miroObj.elevation is EL + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % miro.sourceDistance is r + +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +%Obj.GLOBAL_EmitterDescription =''; +Obj.GLOBAL_RoomDescription = miroObj.location; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..3005699ddefb22c1e876563129116d625051af5a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertLISTEN2SOFA.m @@ -0,0 +1,45 @@ +function Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) +% Obj=SOFAconvertLISTEN2SOFA(LISTEN, subjectID) converts the HRTFs described in LISTEN +% (see LISTEN HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empty conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data + % content_m is [M N], data.IR must be [M R N] +Obj.Data.IR = zeros(size(LISTEN.l_eq_hrir_S.content_m,1),2,size(LISTEN.l_eq_hrir_S.content_m,2)); +Obj.Data.IR(:,2,:)=LISTEN.r_eq_hrir_S.content_m; +Obj.Data.IR(:,1,:)=LISTEN.l_eq_hrir_S.content_m; +Obj.Data.SamplingRate = 48000; % Note: LISTEN.l_eq_hrir_S.sampling_hz contains 44100 which is wrong! + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = subjectID; +Obj.GLOBAL_History='Converted from the LISTEN format'; + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerPosition = [1.95 0 0]; + % Obj.ListenerView = [-1 0 0]; + % Obj.ListenerUp = [0 0 1]; + % Obj.ListenerRotation = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v zeros(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; +Obj.SourcePosition = [LISTEN.l_eq_hrir_S.azim_v LISTEN.l_eq_hrir_S.elev_v 1.95*ones(size(LISTEN.l_eq_hrir_S.elev_v,1),1)]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..8e3f2e47b763dd6ec3cb6e2161081e780b32b8d3 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertMIT2SOFA.m @@ -0,0 +1,86 @@ +function Obj=SOFAconvertMIT2SOFA(root,pinna) +% OBJ=SOFAconvertMIT2SOFA(root,pinna) loads the MIT HRTFs saved in a +% directory ROOT for the PINNA and converts to a SOFA object. +% PINNA must be 'normal' or 'large'. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Create correct parts of the file name +% 'L' use full data from left pinna (normal pinna) +% 'R' use full data from right pinna (large red pinna) +% 'H' use compact data -> not supported now +switch pinna + case 'normal' + postfix='L'; idx=[1 2]; + prefix='full'; + case 'large' + postfix='R'; idx=[2 1]; + prefix='full'; + otherwise + error('Pinna not supported'); +end + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90]; +elecnt=[ 56 60 72 72 72 72 72 60 56 45 36 24 12 1]; + +%% Determine data size +M=sum(elecnt); +Obj.SourcePosition=zeros(M,3); +if isfile([root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav']) + Obj.Data.IR=zeros(M,2,length(audioread([root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav']))); +else + warning(['File not existing: ' root filesep prefix filesep 'elev0' filesep postfix '0e000a.wav' ' --> Please download it to: ' root filesep prefix filesep 'elev0' filesep]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + flip_azi = mod(360-azi,360); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(flip_azi)) 'a.wav']; + Obj.Data.IR(ii,idx(1),:) = audioread(fn)'; % data.IR must be [M R N] + dirfn=dir(fn); + fn=[root filesep prefix filesep 'elev' num2str(ele) filesep postfix num2str(ele) 'e' sprintf('%03d',round(azi)) 'a.wav']; + Obj.Data.IR(ii,idx(2),:) = audioread(fn)'; + % SimpleFreeFieldHRIR 0.2 + % Obj.ListenerRotation(ii,:)=[azi ele 0]; + % SimpleFreeFieldHRIR 0.3 + Obj.SourcePosition(ii,:) = [azi ele 1.4]; + ii=ii+1; + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = ['KEMAR, ' pinna ' pinna']; +Obj.GLOBAL_History='Converted from the MIT format'; +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + +%% Fill the mandatory variables + % SimpleFreeFieldHRIR 0.2 +% Obj.ListenerPosition = [1.4 0 0]; +% Obj.ListenerView = [-1 0 0]; +% Obj.ListenerUp = [0 0 1]; + % SimpleFreeFieldHRIR 0.3 +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..22ffd2e9a97fe84139aa0aa2376744af0099ed88 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSCUT2SOFA.m @@ -0,0 +1,75 @@ +function Obj=SOFAconvertSCUT2SOFA(root,r) +% OBJ=SOFAconvertSCUT2SOFA(root,pinna) loads the SCUT HRTFs saved in a +% directory ROOT for the radius R and converts to a SOFA object. +% R must be in meters. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define elevations +eles = [-30 -15 0 15 30 45 60 75 90]; +elecnt=[ 72 72 72 72 72 72 36 24 1]; + +%% Create empty matrix +M=sum(elecnt)*length(r); +Obj.SourcePosition=zeros(M,3); +Obj.Data.IR=zeros(M,2,512); + +%% Fill with data +Obj.Data.SamplingRate = 44100; +ii=1; +for jj=1:length(r) + for ei = 1 : length(eles) + ele = eles(ei); + for ai = 0 : elecnt(ei)-1 + azi = 360/elecnt(ei)*ai; + fn=fullfile(root, ['r' num2str(r(jj)*100)], ['ele' num2str(ele)], ['H' num2str(azi) 'c.pcm']); + dirfn=dir(fn); + if isempty(dirfn) % check if HRTF sources are available + error(['HRTF files not available in: ' fullfile(root, ['r' num2str(r(jj)*100)], ['ele' num2str(ele)])]); + end + fid = fopen(fn, 'r'); + H = fread(fid,'float'); + fclose(fid); + Obj.Data.IR(ii,1,:) = single(H(1:2:1024)); % separate the left-ear HRIR + Obj.Data.IR(ii,2,:) = single(H(2:2:1024)); % separate the right-ear HRIR + Obj.SourcePosition(ii,:) = [mod(360-azi,360) ele r(jj)]; + ii=ii+1; + end + end +end + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the SCUT format'; + +Obj.GLOBAL_Author = 'Bosun Xie'; +Obj.GLOBAL_AuthorContact = 'phbsxie@scut.edu.cn'; +Obj.GLOBAL_License = 'CC 3.0 BY-SA-NC'; +Obj.GLOBAL_Organization = 'South China University of Technology, Guangzhou, China'; + +Obj.GLOBAL_References = 'Bosun Xie, 2013, "Head-Related Transfer Function and Virtual Auditory Display", J Ross Publishing Inc., Plantation, FL, USA'; +Obj.GLOBAL_RoomType = 'free field'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_DatabaseName='SCUT'; + +Obj.GLOBAL_DateCreated = datestr(datenum(dirfn.date),SOFAdefinitions('dateFormat')); + + +%% Fill the mandatory variables +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..0391042cc29b57888ad059573cce7d16ffc4c544 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSOFA2ARI.m @@ -0,0 +1,70 @@ +function [hM,meta,stimPar]=SOFAconvertSOFA2ARI(Obj) +% [hM, meta, stimPar]=SOFAconvertSOFA2ARI(Obj) converts a SOFA object HRTFs +% to HRTFs described in hM, meta, and stimPar (see ARI HRTF format). +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +if ~strcmp(Obj.GLOBAL_SOFAConventions,'SimpleFreeFieldHRIR'), + error('ARI Format supports only SimpleFreeFieldHRIR SOFA conventions'); +end + +%% Fill data matrix +hM=shiftdim(Obj.Data.IR,2); % data.IR is [M R N], hM must be [N M R] + +%% Fill stimPar +stimPar.SamplingRate = Obj.Data.SamplingRate; +stimPar.TimeBase = 1e6/stimPar.SamplingRate; +stimPar.SubjectID = Obj.GLOBAL_ListenerShortName; + +%% Fill meta + % Fill in geodesic coordinate system where azi=(0;360) and ele=(-90;90); +meta.pos(:,1)=bsxfun(@times,Obj.SourcePosition(:,1),ones(Obj.API.M,1)); +meta.pos(:,2)=bsxfun(@times,Obj.SourcePosition(:,2),ones(Obj.API.M,1)); + % Fill in the Channel +if isfield(Obj,'MeasurementSourceAudioChannel'), + meta.pos(:,3) = bsxfun(@times,Obj.MeasurementSourceAudioChannel,ones(Obj.API.M,1)); +else + meta.pos(:,3) = NaN(Obj.API.M,1); +end +if isfield(Obj,'MeasurementAudioLatency'), + meta.lat=bsxfun(@times,Obj.MeasurementAudioLatency,ones(Obj.API.M,1)); +end + % create horizontal-polar coordinates +[meta.pos(:,6), meta.pos(:,7)]=sph2hor(meta.pos(:,1),meta.pos(:,2)); + % create continuous-elevation coordinates where azi=(-90;90) and ele=(0;360); +meta.pos(:,4)=meta.pos(:,1); +meta.pos(:,5)=meta.pos(:,2); +idx=find(meta.pos(:,1)>90 & meta.pos(:,1)<=270); +meta.pos(idx,4)=meta.pos(idx,4)-180; +meta.pos(idx,5)=180-meta.pos(idx,5); +idx=find(meta.pos(:,1)>270 & meta.pos(:,1)<=360); +meta.pos(idx,4)=meta.pos(idx,4)-360; + +%% Fill with unknown but probably mandatory data +% stimPar.Channel = 0; +% stimPar.Electrode = 0; +% stimPar.PulseNr = 0; +% stimPar.Period = 0; +% stimPar.Offset = 0; +stimPar.Resolution = 24; % assume a 24-bit ADC/DAC resolution +% stimPar.FadeIn = 0; +% stimPar.FadeOut = 0; +% stimPar.Length = 0; +% stimPar.FittFileName = ''; +% stimPar.StimFileName = ''; +stimPar.GenMode = 1; +% stimPar.WorkDir = ''; +stimPar.ID = 'hrtf'; +stimPar.Version = '2.0.0'; + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..dc01c37d17278e811c683381bcd8151b1ed24129 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertSYMARE2SOFA.m @@ -0,0 +1,79 @@ +function [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) +% [Obj] = SOFAconvertSYMARE2SOFA(SYMAREpath,HRIRname) converts objects +% from SYMARE database to Struct in SOFA format. +% +% SYMAREpath of type string specifies the path where the SYMARE directory +% is found +% HRIRname of type string specifies which HRIR out of the +% <SYMAREpath>/HRIRs/Acoustic directory should be converted +% +% Returns Obj in SOFA format which can further be converted into .sofa +% file using SOFAsave + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: license added, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Get an empty conventions structure + +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); +Obj.GLOBAL_Title = 'HRIR'; +Obj.GLOBAL_RoomType = 'free field'; + +%% Fill global attributes +if isempty(strfind(HRIRname,'.mat')) + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-1:end)); +else + Obj.GLOBAL_ListenerShortName = strcat('Subj_',HRIRname(end-5:end-4)); +end + +Obj.GLOBAL_AuthorContact ='https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_Comment = ''; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History', ... + 'Converted from the SYMARE database'); +Obj.GLOBAL_License = strcat('Creative Commons Attribution-Non', ... + 'Commercial-ShareAlike 4.0 International Public License'); +Obj.GLOBAL_Organization = 'University of Sydney'; +Obj.GLOBAL_Author = 'Craig Jin, Anthony Tew, et al.'; +Obj.GLOBAL_Origin = 'https://www.morphoacoustics.org/resources.html'; +Obj.GLOBAL_DateCreated = char(datetime('now','Format','yyyy-MM-dd HH:mm:ss.SSS')); +Obj.GLOBAL_DatabaseName='SYMARE'; + +%% Get SYMARE data and convert to SOFA structure +%m: number of measurements; +%R: number of receivers; +%n: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%HRIR Dimensions : mRn; + +% Get source positions +load(fullfile(SYMAREpath,'HRIRs','Parameters','azim')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','elev')); +load(fullfile(SYMAREpath,'HRIRs','Parameters','r')); +if ~(length(r) == length(azim)) + r(1:size(azim)) = r; + r = r'; +end +Obj.SourcePosition = [azim*180/pi,elev*180/pi,r]; + +% Get sampling frequency +load(fullfile(SYMAREpath,'HRIRs','Parameters','fs')); +Obj.Data.SamplingRate = fs; + +% Get IRs +load(fullfile(SYMAREpath,'HRIRs','Acoustic',HRIRname)); % gets you hR, hL +HRIR(:,:,1) = hL'; % nm -> mnR +HRIR(:,:,2) = hR'; % nm -> mnR +Obj.Data.IR = permute(HRIR,[1 3 2]); % mnR -> mRn + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..fd91231c5bd1be5a55cae700903939129f39b8cf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTHK2SOFA.m @@ -0,0 +1,143 @@ +function Obj = SOFAconvertTHK2SOFA(miroObj) +% OBJ=SOFAconvertTHK2SOFA(miroObj) converts the HRIRs, BRIRs, and DRIRs +% (VariSphear array measurements) described in miroObj to SOFA. +% miroObj is the miro object saved at the Technische Hochschule Koeln, provided by Benjamin Bernschuetz. +% Reference to the source format: http://www.audiogroup.web.th-koeln.de/FILES/miro_documentation.pdf +% Reference to the source coordinate system: [1] http://www.audiogroup.web.th-koeln.de/SOFiA_wiki/COORDINATES.html +% SOFAconvertTHK2SOFA written by Tim Lübeck, TH Köln, 2018 +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% +%if isoctave, +if exist('OCTAVE_VERSION','builtin') ~= 0 + error(['Octave is not able to convert THK to SOFA, use Matlab instead.']); +end + +%% Get an empty conventions structure depending on miro format +if ( strcmp (miroObj.type,'HRIR') ) + Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + Obj.GLOBAL_Title = 'HRIR'; + Obj.GLOBAL_RoomType = 'free field'; + typeFlag = 0; +elseif ( strcmp (miroObj.type,'BRIR') ) + Obj = SOFAgetConventions('MultiSpeakerBRIR'); + Obj.GLOBAL_Title = 'BRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 1; +else %( strcmp (miroObj.type,'MICARRAY') ) + Obj = SOFAgetConventions('SingleRoomDRIR'); + Obj.GLOBAL_Title = 'DRIR'; + Obj.GLOBAL_RoomType = 'reverberant'; + typeFlag = 2; +end + +%% Fill global attributes +Obj.GLOBAL_ListenerShortName = miroObj.name; +Obj.GLOBAL_AuthorContact = miroObj.contact; +Obj.GLOBAL_Comment = [miroObj.context,' / Sampling Grid: ',miroObj.quadGrid]; +Obj.GLOBAL_History = SOFAappendText(Obj,'GLOBAL_History','Converted from the miro file format'); +Obj.GLOBAL_License = 'CC 3.0 BY-SA'; +Obj.GLOBAL_Organization = 'Technische Hochschule Koeln, Germany'; +Obj.GLOBAL_Author = miroObj.engineer; +Obj.GLOBAL_Origin = 'http://audiogroup.web.th-koeln.de'; +Obj.GLOBAL_DateCreated = datestr(datenum(miroObj.date),'yyyy-mm-dd HH:MM:SS'); +Obj.GLOBAL_DatabaseName='THK'; +Obj.GLOBAL_ListenerDescription = miroObj.microphone; +Obj.GLOBAL_ReceiverDescription = [miroObj.microphone '; ' miroObj.micPreamp]; +Obj.GLOBAL_SourceDescription = miroObj.source; +Obj.GLOBAL_EmitterDescription = miroObj.source; +Obj.GLOBAL_RoomDescription = [miroObj.location,' / avgAirTemp: ',num2str(miroObj.avgAirTemp),' / avgRelHumidity: ',num2str(miroObj.avgRelHumidity)]; + +%% Set miroObj to degree mode +miroObj.shutUp = 1; +miroObj = setDEG(miroObj); + +%% Get miroObject data and convert to SOFA structure +%M: number of measurements; +%R: number of receivers; +%N: number of data samples describing one measurement. Data is a function of N; +%E: number of emitters; +%C: coordinate dimension, always three with the meaning +%FIR : [M R N]; + +if (typeFlag == 0 || typeFlag == 1) %BRIR or HRIR + irChOne = zeros(miroObj.returnTaps,miroObj.nIr); + irChTwo = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + IR = getIR( miroObj, channel ); + irChOne(:, channel) = IR(:,1); %[N M] + irChTwo(:, channel) = IR(:,2); %[N M] + end + if (typeFlag == 0) %HRIR + Obj.Data.IR = irChOne; % irChOne is [N M] + Obj.Data.IR(:,:,2) = irChTwo; + Obj.Data.IR = shiftdim(Obj.Data.IR,1); % convert from [N M R] to [M R N] + else % BRIR + Obj.Data.IR = zeros(size(irChOne,2), 2, 1, size( irChTwo,1)); %[N 2 1 M] + Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irChOne,-2),3); + Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irChTwo,-2),3); + end +else % DRIR + irData = zeros(miroObj.returnTaps,miroObj.nIr); + for channel = 1 : miroObj.nIr + irData(:,channel) = miroObj.getIR(channel); + end + Obj.Data.IR = zeros(1, miroObj.nIr ,miroObj.returnTaps); %[M R N] + for R = 1 : miroObj.nIr + Obj.Data.IR(1,R,:) = irData(:,R); + end + Obj.Data.Delay = zeros(1,miroObj.nIr); +end +Obj.Data.SamplingRate = miroObj.fs; + +%% Fill the mandatory source emitter variables +Obj.ListenerPosition = [0 0 0]; % for BRIR and HRIR listener in center +Obj.ReceiverPosition = [0 +miroObj.radius 0; 0 -miroObj.radius 0]; % for HRIR and BRIR ears as receiver + +if (typeFlag == 0)%HRIR + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.SourcePosition = [... + miroObj.azimuth' ... % azimuth angle in a range of (0-360°(. Whereas AZ=0° is defined to be the front direction and AZ=180° to be the rear direction. + 90-miroObj.elevation' ... % elevation angle in range of (0-180°). EL=0 points upwards, EL=90° points to the horizontal plane and EL=180° points downwards. + miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; % radius in meters +elseif (typeFlag == 1) %BRIR + Obj.SourcePosition = [0 0 0]; % default edit manually! + Obj.EmitterPosition = [miroObj.sourceDistance 0 0]; % default position is center, otherwise define manually + Obj.EmitterPosition_Type = 'cartesian'; + Obj.EmitterUp = [0 0 1]; + Obj.EmitterView = [-1 0 0]; + Obj.ListenerView = [miroObj.azimuth', ... % see HRIR definitions + 90-miroObj.elevation', ... + zeros(size(miroObj.azimuth'))]; %miroObj.sourceDistance*ones(size(miroObj.azimuth'))]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ListenerUp = [0 0 1]; +else %DRIR + Obj.SourcePosition = [1,0,0]; % default edit manually! + Obj.EmitterPosition = [0,0,0]; + Obj.ListenerPosition = [0 0 0]; + Obj.ListenerView = [1 0 0]; + Obj.ListenerUp = [0 0 1]; + Obj.ListenerView_Type = 'spherical'; + Obj.ListenerView_Units = 'degree, degree, metre'; + Obj.ReceiverPosition = [... + miroObj.azimuth' ... + 90-miroObj.elevation' ... + miroObj.radius*ones(size(miroObj.azimuth'))]; + Obj.ReceiverPosition_Type = 'spherical'; + Obj.ReceiverPosition_Units = 'degree, degree, metre'; +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..6f1150b3fafdaf770745aae0f1544c8ef2540233 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlin2SOFA.m @@ -0,0 +1,58 @@ +function Obj=SOFAconvertTUBerlin2SOFA(irs) +% OBJ=SOFAconvertTUBerlin2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Fill data with data +Obj.Data.IR = shiftdim(shiftdim(irs.left,-1),2); % irs.left is [N M], data.IR must be [M R N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-1),2); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'HRTF from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['H. Wierstorf, M. Geier, A. Raake, S. Spors. ', ... + 'A Free Database of Head-Related Impulse Response Measurements in ', ... + 'the Horizontal Plane with Multiple Distances. ', ... + 'In 130th Convention of the Audio Engineering Society, May 2011.']; +Obj.GLOBAL_Origin = 'https://dev.qu.tu-berlin.de/projects/measurements/repository/show/2010-11-kemar-anechoic/mat'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'HRTF'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = irs.ears; +Obj.GLOBAL_SourceDescription = irs.source; + +%% Fill the mandatory variables +% SimpleFreeFieldHRIR 0.6 +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.SourcePosition = [nav2sph(rad2deg(irs.apparent_azimuth)') ... + rad2deg(irs.apparent_elevation)' ... + distance.*ones(M,1)]; +Obj.ListenerPosition = [0 0 0]; +Obj.ListenerView = [1 0 0]; +Obj.ListenerUp = [0 0 1]; + + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..4c24ed7d1de931345f17044705ff6d144bcf74ff --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAconvertTUBerlinBRIR2SOFA.m @@ -0,0 +1,74 @@ +function Obj=SOFAconvertTUBerlinBRIR2SOFA(irs) +% OBJ=SOFAconvertTUBerlinBRIR2SOFA(irs) converts the HRTFs described in irs +% (see TU-Berlin HRTF format) to a SOFA object, using the MultiSpeakerBRIR +% Convention. +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: doc fixed, header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +Obj = SOFAgetConventions('MultiSpeakerBRIR'); + +%% Fill data with data +Obj.Data.IR = zeros(size(irs.left,2),2,1,size(irs.left,1)); +Obj.Data.IR(:,1,:) = shiftdim(shiftdim(irs.left,-2),3); % irs.left is [N M], data.IR must be [M R E N] +Obj.Data.IR(:,2,:) = shiftdim(shiftdim(irs.right,-2),3); +Obj.Data.SamplingRate = irs.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History='Converted from the TU-Berlin format'; +Obj.GLOBAL_Comment = irs.description; +Obj.GLOBAL_License = 'Creative Commons Attribution-NonCommercial-ShareAlike 3.0'; +Obj.GLOBAL_ApplicationName = 'BRIR from TU Berlin'; +Obj.GLOBAL_ApplicationVersion = '1.0'; +Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; +Obj.GLOBAL_References = ['']; +Obj.GLOBAL_Origin = 'TU Berlin'; +Obj.GLOBAL_Organization = 'Quality and Usability Lab, Technische Universitaet Berlin'; +Obj.GLOBAL_DatabaseName = 'TU Berlin'; +Obj.GLOBAL_Title = 'BRIR TU Berlin'; +Obj.GLOBAL_ListenerDescription = irs.head; +Obj.GLOBAL_ReceiverDescription = 'Large ears (KB0065 + KB0066) with G.R.A.S. 40AO pressure microphones'; +Obj.GLOBAL_SourceDescription = 'Genelec 8030A'; +Obj.GLOBAL_RoomType = 'reverberant'; +Obj.GLOBAL_RoomDescription = ''; + + +%% Fill the mandatory variables +% MultiSpeakerBRIR +% === Source === +Obj.SourcePosition = [0 0 0]; % center of loudspeaker array +Obj.EmitterPosition = irs.source_position'; +Obj.EmitterView = irs.head_position'; +Obj.EmitterUp = [0 0 1]; +% === Listener === +% number of measurements +M = length(irs.apparent_elevation); +distance = sqrt(sum((irs.source_position-irs.head_position).^2)); +Obj.ListenerPosition = irs.head_position'; +[x,y,z] = sph2cart(fixnan(irs.head_azimuth'), ... + repmat(fixnan(irs.head_elevation'),size(irs.head_azimuth')), ... + repmat(distance,size(irs.head_azimuth'))); +Obj.ListenerView = [x,y,z]; +Obj.ListenerUp = [0 0 1]; +% Receiver position for a dummy head (imported from SimpleFreeFieldHRIR) +Obj.ReceiverPosition = [0,0.09,0; 0,-0.09,0]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +end + +function x = fixnan(x) + if isnan(x), x=0; end +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m new file mode 100644 index 0000000000000000000000000000000000000000..ac6cb698bbbb9bebf1c320e6fe4633fc230aef7d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/converters/SOFAhrtf2dtf.m @@ -0,0 +1,172 @@ +function [dtf,ctf]=SOFAhrtf2dtf(hrtf,varargin) +%SOFAHRTF2DTF splits HRTFs into directional transfer functions (DTFs) and +%common transfer functions (CTFs) +% Usage: [dtf,ctf]=SOFAhrtf2dtf(hrtf) +% [dtf,ctf]=SOFAhrtf2dtf(hrtf,f1,f2) +% +% Input parameters: +% hrtf: SOFA object with SimpleFreeFieldHRIR convention +% +% Output arguments: +% dtf: SOFA object with the directional transfer functions +% ctf: SOFA object with the common transfer functions +% +% `SOFAhrtf2dtf(...)` calculates DTFs using the method from either +% Majdak et al. (2010; 'log' flag) or Middlebrooks (1999; 'rms' flag). +% The magnitude spectrum of the CTF is calculated by +% averaging the (log-)magnitude spectra across all HRTFs for each ear. +% The phase spectrum of the CTF is the minimum phase +% corresponding to the magnitude spectrum of the CTF. +% DTFs result from filtering the HRTF with the inverse complex CTF. +% +% `SOFAhrtf2dtf` accepts the following key-value pairs: +% +% 'f1',f1 start frequency of the filtering (in Hz; default: 50 Hz) +% 'f2',f2 end frequency of the filtering (in Hz; default: 18 kHz) +% 'atten',a broadband attenuation in order to avoid clipping (in dB; +% default: 20 dB) +% 'weights' w area weights for averaging. Vector of size [M 1] +% (M=number of HRIRs), or flase (default: false) +% +% `SOFAhrtf2dtf` accepts the following flags: +% +% 'log' evaluate CTF magnitude spectrum by average of log-magnitude +% spectra, equivalent to geometric mean of linear filters +% (c.f., Majdak et al., 2010; Baumgartner et al., 2014). +% This is the default. +% 'rms' evaluate CTF magnitude spectrum by RMS of linear +% magnitude spectra, equivalent to diffuse-field +% compensation (c.f., Middlebrooks, 1999; Moller et al., +% 1995). +% +% References: +% Baumgartner, R., Majdak, P., & Laback, B. (2014). Modeling sound-source +% localization in sagittal planes for human listeners. J. Acoust. Soc. Am. +% 136(2), 791-802. +% Majdak, P., Goupell, M. J., & Laback, B. (2010). 3-D localization of +% virtual sound sources: Effects of visual environment, pointing method, +% and training. Attention, Perception, & Psychophysics, 72(2), 454-469. +% Middlebrooks, J. C. (1999). Individual differences in external-ear +% transfer functions reduced by scaling in frequency. J. Acoust. Soc. Am., +% 106(3), 1480-1492. +% Moller, H., Hammershoi, D., Jensen, C. B., S?rensen, M. F. (1995). +% Design criteria for headphones. J. Audio Eng. Soc., 43(4), 218-232. + +% #Author: Robert Baumgartner (16.01.2014) +% #Author: Fabian Brinkmann: added rms, and weighted averaging (08.09.2016) +% #Author: Piotr Majdak: Octave ifft compatibility (23.02.2018) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Check Input +definput.keyvals.f1 = 50; % Hz +definput.keyvals.f2 = 18000; % Hz +definput.keyvals.atten = 20; % dB +definput.keyvals.weights = false; +definput.flags.avg = {'log','rms'}; + +[flags,kv]=SOFAarghelper({'f1','f2','atten', 'weights'},definput,varargin); + +%% Settings +kv.fs = hrtf.Data.SamplingRate; +hrtfmtx = shiftdim(hrtf.Data.IR,2); % dim 1: time, dim 2: source position, dim 3: receiver/ear +N = size(hrtfmtx,1); +Nfft = N; %2^nextpow2(N); + +%% Frequency bounds +df = kv.fs/Nfft; +f = 0:df:kv.fs-df; +idx = f >= kv.f1 & f <= kv.f2; +idx(Nfft/2+2:end) = fliplr(idx(2:Nfft/2)); + +%% CTF calculation + +% get magnitude response +hrtff=fft(hrtfmtx,Nfft); +if flags.do_rms + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg=sqrt(sum( abs(hrtff).^2 .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2 )); + else + ctffavg=sqrt(mean(abs(hrtff).^2,2)); + end +else % flags.do_log + if any(kv.weights) + kv.weights = squeeze(kv.weights) / sum(kv.weights); + ctffavg= sum(log(abs(hrtff)+eps) .* repmat(kv.weights', [hrtf.API.N 1 hrtf.API.R]), 2); + else + ctffavg=mean(log(abs(hrtff)+eps),2); + end +end + +% Force minimum phase +ctfflog=mean(log(abs(hrtff)+eps),2); +ctfcep = ifft(ctfflog,Nfft); +ctfcep(Nfft/2+2:Nfft,:,:) = 0; % flip acausal part to causal part or simply multiply +ctfcep(2:Nfft/2,:,:) = 2*ctfcep(2:Nfft/2,:,:); % causal part by 2 (due to symmetry) +ctfflog = fft(ctfcep,Nfft); +ctfp = exp(ctfflog); + +% get complex spectrum +if flags.do_rms + ctff = ctffavg .*exp(1j*angle(ctfp)); +else + ctff = exp(ctffavg) .*exp(1j*angle(ctfp)); +end + +% get IR +ctfmtx = real(ifft(ctff, Nfft)); + +%% DTF calculation +dtff = hrtff; +dtff(idx,:,:) = hrtff(idx,:,:)./repmat(ctff(idx,:,:),[1 size(hrtff,2) 1]); +dtfmtx = ifft(dtff,Nfft); + +%% Attenuate to avoid clipping +ctfmtx = ctfmtx / 10^(kv.atten/20); +dtfmtx = dtfmtx / 10^(kv.atten/20); + +%% Output Objects +dtf = hrtf; +if size(dtfmtx,3)==1 % handle objects with R=1 + dtfmtx(1,1,2)=0; + dtfmtx = shiftdim(dtfmtx,1); + dtf.Data.IR = dtfmtx(:,1,:); +else + dtf.Data.IR = shiftdim(dtfmtx,1); +end +if ~isfield(dtf, 'GLOBAL_Comment'), dtf.GLOBAL_Comment=''; end +dtf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Directional transfer functions (DTFs) were generated by removing from the HRTFs the direction-independent log-amplitude spectrum for each ear.']; + +ctf = hrtf; +if size(ctfmtx,2)==1 % handle objects with R=1 + ctf.Data.IR = shiftdim(shiftdata([ctfmtx ctfmtx],3),2); + ctf.Data.IR = ctf.Data.IR(1,:,:); +else + ctf.Data.IR = shiftdim(ctfmtx,1); +end +ctf.GLOBAL_Comment = [dtf.GLOBAL_Comment '. Common transfer functions (CTFs) were extracted from the HRTFs in terms of averaging the log-amplitude spectrum for each ear. The phase of a CTF is determined as minimum phase.']; +ctf.SourcePosition = [0 0 0]; + % remove non-standard variables +fc=fieldnames(ctf); +fo=fieldnames(SOFAgetConventions(ctf.GLOBAL_SOFAConventions)); +f=setdiff(fc,fo); % get non-standard fields +f(strncmpi(f,'GLOBAL_',7)) = []; % variables only +ctf=rmfield(ctf,f); % remove +ctf.API.Dimensions=rmfield(ctf.API.Dimensions,f); +ctf = SOFAupdateDimensions(ctf); + + +function f=myifftreal(c,N) % thanks goto the LTFAT <http://ltfat.sf.net> +if rem(N,2)==0 + f=[c; flipud(conj(c(2:end-1,:)))]; +else + f=[c; flipud(conj(c(2:end,:)))]; +end; +f=real(ifft(f,N,1)); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..780bb8e50218d149806f89e16ed5643b552b9dc4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/hor2sph.m @@ -0,0 +1,39 @@ +function [azi,ele]=hor2sph(lat,pol) +%HOR2SPH transform horizontal-polar to spherical coordinates. +% [azi,ele]=hor2sph(lat,pol) +% +% Input: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also SPH2HOR, SPH2NAV, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Robert Baumgartner +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - function hor2sph +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[x,nz,y] = sph2cart(-deg2rad(pol),deg2rad(lat),ones(size(lat))); + +[azi,ele,r] = cart2sph(x,y,-nz); + +azi = rad2deg(azi); +ele = rad2deg(ele); + +% adjust azimuth range +[azi,ele] = nav2sph(azi,ele); + +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m new file mode 100644 index 0000000000000000000000000000000000000000..47e34d2bfc09f535f55b98b6f8ad586bacc9378f --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/nav2sph.m @@ -0,0 +1,28 @@ +function [azi,ele]=nav2sph(azi,ele) +%NAV2SPH Coordinate Transform. +% [azi,ele] = nav2sph(azi,ele) vonverts navigational coordinates to +% spherical coordinates. +% +% Input: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% See also HOR2SPH, SPH2HOR, SPH2NAV, SPH2HOR, SPH2SH + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function nav2sph +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +idx=find(azi<0); % azi between -180 and 0 deg +azi(idx) = azi(idx)+360; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m new file mode 100644 index 0000000000000000000000000000000000000000..d9ee4571c2360363c9c511f62b7c840a43990773 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2SH.m @@ -0,0 +1,64 @@ +function [S, N_SH] = sph2SH(dirs, L) +%[S, N_SH] = sph2SH(dirs, L); +% sph2SH calculates real-valued spherical harmonics for directions dirs = [azi ele] (in degrees) up to order L. +% +% Input: +% dirs ... dirs = [azi ele] +% L ... order L +% +% Output: +% S ... real-valued spherical harmonics +% N_SH ... number of SH coefficients +% +% See also HOR2SPH, SPH2HOR, SPH2NAV, SPH2HOR, NAV2SPH + +% #Author: Piotr Majdak: adapted from getSH.m from https://github.com/polarch/Spherical-Harmonic-Transform (24.07.2020) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - function sph2SH +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + + N_dirs = size(dirs, 1); % number of discrete positions + N_SH = (L+1)^2; % number of SH coefficients + dirs=deg2rad(dirs); % convert to radiant + dirs(:,2) = pi/2 - dirs(:,2); % convert to zenith angle + + S = zeros(N_SH, N_dirs);% matrix with the coefficients + + % n = 0, direction-independent component + Llm = legendre(0, cos(dirs(:,2)')); + Nlm = sqrt(1./(4*pi)) * ones(1,N_dirs); + CosSin = zeros(1,N_dirs); + CosSin(1,:) = ones(1,size(dirs,1)); + S(1, :) = Nlm .* Llm .* CosSin; + + % n > 0, direction-dependent components + idx = 1; + for l=1:L + + m = (0:l)'; + + Llm = legendre(l, cos(dirs(:,2)')); + condon = (-1).^[m(end:-1:2);m] * ones(1,N_dirs); + Llm = condon .* [Llm(end:-1:2, :); Llm]; + + mag = sqrt( (2*l+1)*factorial(l-m) ./ (4*pi*factorial(l+m)) ); + % create the ACN ordering: [m<0; m=0; m>0] + Nlm = [mag(end:-1:2) * ones(1,N_dirs); mag * ones(1,N_dirs)]; + + CosSin = zeros(2*l+1,N_dirs); + CosSin(l+1,:) = ones(1,size(dirs,1)); % m=0 + CosSin(m(2:end)+l+1,:) = sqrt(2)*cos(m(2:end)*dirs(:,1)'); % m>0 + CosSin(-m(end:-1:2)+l+1,:) = sqrt(2)*sin(m(end:-1:2)*dirs(:,1)'); % m<0 + + S(idx+1:idx+(2*l+1), :) = Nlm .* Llm .* CosSin; + idx = idx + 2*l+1; + end + + S = S.'; diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m new file mode 100644 index 0000000000000000000000000000000000000000..420dca0c384161169a60aeecb94de7cb1676ca37 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2hor.m @@ -0,0 +1,42 @@ +function [lat,pol]=sph2hor(azi,ele) +%SPH2HOR transform spherical to horizontal-polar coordinates. +% [lat,pol]=sph2hor(azi,ele) +% +% Input: +% azi ... azimuth (in degrees) +% ele ... elevation (in degrees) +% +% Output: +% lat ... lateral angle (-90 <= lat <= 90) +% pol ... polar angle (-90 <= pol < 270) +% +% See also HOR2SPH, SPH2NAV, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Robert Baumgartner +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function sph2hor +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and +% limitations under the License. + +[x,y,z] = sph2cart(deg2rad(azi),deg2rad(ele),ones(size(azi))); + +% remove noise below eps +x(abs(x)<eps)=0; +y(abs(y)<eps)=0; +z(abs(z)<eps)=0; + +% interpret horizontal polar format as rotated spherical coordinates with +% negative azimuth direction +[pol,nlat,r] = cart2sph(x,z,-y); +pol = rad2deg(pol); +lat = rad2deg(-nlat); + +% adjust polar angle range +pol = mod(pol+90,360)-90; +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m new file mode 100644 index 0000000000000000000000000000000000000000..b7fe3a0c403676c717a68340517f6be50609b20e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/coordinates/sph2nav.m @@ -0,0 +1,31 @@ +function [azi,ele] = sph2nav(azi,ele) +%SPH2NAV Coordinate Transform +% [azi,ele] = sph2nav(azi,ele) converts spherical coordinates to +% navigational coordinates. +% +% Input: +% azi ... azimuth (0 <= azi < 360) +% ele ... elevation (-90 <= ele <= 90) +% +% Output: +% azi ... azimuth (-180 <= azi <= 180) +% ele ... elevation (-90 <= ele <= 90) +% +% See also HOR2SPH, SPH2HOR, SPH2HOR, SPH2SH, NAV2SPH + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function sph2nav +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; Wolfgang Hrauda +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +azi=mod(azi,360); % wrap to 0 to 360 +idx=find(azi>180 & azi<=360); % azi between 180 and 360 +azi(idx) = -(360-azi(idx)); + +end % end of function \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..fa7d95ab7951c36b00f6a13d273a8c41a131770e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_ARI2SOFA.m @@ -0,0 +1,46 @@ +% SOFA Toolbox - demo script +% Load HRTF in ARI format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert (use default if not defined) +if ~exist('subjectID','var'); subjectID='NH4'; end +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); + +if isfile(ARIfn) + disp(['Loading: ' ARIfn]); + ARI=load(ARIfn); +else + warning(['File not existing: ' ARIfn ' --> Please download it from http://www.oeaw.ac.at/isf/hrtf and save it to: ' fullfile(fileparts(SOFAdbPath), 'ARI', subjectID)]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + + +%% convert +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); +Obj.GLOBAL_DatabaseName = 'ARI'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['ARI_' subjectID '_' ARIfile '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..fd2d65d51aa277fe06fa29aa48b05178b58d688a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_BTDEI2SOFA.m @@ -0,0 +1,65 @@ +% SOFA Toolbox demo script +% load HRTF in BT-DEI format and save in SOFA format. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Headphone index of the files to convert +hp= 'H010'; +% Subject index of the files to convert +subject= 'S115'; +% Measurement index of the files to convert +setm= 'Set02'; %Set01 Set02 ... +% File name of the BTDEI file +BTDEIfold='COMPENSATED'; %RAW %COMPENSATED %EQUALIZED +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load BTDEI file \ load database structure data +f=filesep; +BTDEI_hp_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,'headphones_info.mat'); +BTDEI_add=fullfile(fileparts(SOFAdbPath),'BTDEI',hp,subject,setm,BTDEIfold,'MAT',[hp '_' subject '_btdei.mat']); +disp(['Loading BT-DEI data']); + +try + datasheet = load(BTDEI_hp_add); + BTDEI.hp = datasheet.hp_specs; + + switch subject + case 'S115' + BTDEI.sbjType = 'dummy head with large pinna'; + case 'S116' + BTDEI.sbjType = 'dummy head without pinna'; + case 'S117' + BTDEI.sbjType = 'dummy head without pinna'; + otherwise + BTDEI.sbjType = 'human'; + end + + container = load(BTDEI_add); + BTDEI.specs = container.specs; + BTDEI.data = container.data; +catch e + error(['Load BTDEI file - Error message: ' e.message ' Try downloading the BT-DEI database from: http://padva.dei.unipd.it/?page_id=345 to the corresponding directory.']); +end + +BTDEI.type = BTDEIfold; +BTDEI.typeset = setm; + +%% convert +Obj = SOFAconvertBTDEI2SOFA(BTDEI); +Obj.GLOBAL_Comment = SOFAappendText(Obj,'GLOBAL_Comment',BTDEIfold); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['BTDEI-hp_' hp '_subj_' subject '-' setm '-' BTDEIfold '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..eb571b48a7bc3180ed0d3c54273e218c855120b2 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_CIPIC2SOFA.m @@ -0,0 +1,36 @@ +% load HRTF in CIPIC format and save in SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences; +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID=3; +% File name of the CIPIC file +CIPICfile='hrir_final'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% load CIPIC file +CIPICfn=fullfile(fileparts(SOFAdbPath), 'CIPIC', ['subject_' sprintf('%03d',subjectID)], [CIPICfile '.mat']); +disp(['Loading: ' CIPICfn]); +CIPIC=load(CIPICfn); + +%% convert +Obj=SOFAconvertCIPIC2SOFA(CIPIC); +Obj.GLOBAL_DatabaseName = 'CIPIC'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test', ['CIPIC_' 'subject_' sprintf('%03d',subjectID) '_' CIPICfile '.sofa']); +disp(['Saving: ' SOFAfn]) +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..d512029cc8035c7142936b6c4b0ccac51f208006 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FHK2SOFA.m @@ -0,0 +1,50 @@ +% load HRTF in FHK format and save in SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Octave has no support for the miro class of the FHK data +% if isoctave +if exist('OCTAVE_VERSION','builtin') ~= 0 + warning(['demo_FHK2SOFA does not work in Octave.' newline 'Octave is not able to convert FHK to SOFA, use Matlab instead.']); + return; +end + +% load HRTF in FHK format and save as SOFA format + +%% Define parameters +% Get a file name of the FHK directory +d=dir(fullfile(fileparts(SOFAdbPath),'FHK','HRIR_*.mat')); +if isempty(d) + error(['No HRTF files available: ' fullfile(fileparts(SOFAdbPath),'FHK','HRIR_*.mat')]); +end +fn=d(1).name; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load FHK file +FHKfn=fullfile(fileparts(SOFAdbPath), 'FHK', fn); +disp(['Loading: ' FHKfn]); +FHK=load(FHKfn); +FHKvar=fieldnames(FHK); +FHKname=FHKvar{1}; +FHKdata=FHK.(FHKname); + +%% convert +Obj=SOFAconvertFHK2SOFA(FHKdata); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['FHK_' FHKname '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m new file mode 100644 index 0000000000000000000000000000000000000000..ca59a8a3a635465cc59078c3ccca141eb58b7033 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldDirectivityTF.m @@ -0,0 +1,74 @@ +% Demonstrates the usage of the FreeFieldDirectivityTF conventions. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: '(demo_)plot_trumpet_directivity' added to this script (19.02.2022) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% close all; + +clear fn; +fn{1}='ITA_Dodecahedron.sofa'; +fn{2}='Trumpet_modern_et_ff_all_tensorData.sofa'; +% fn{3}='Trumpet_modern_et_ff_a4_rawData.sofa'; % (21 MB!!! uncomment if you don't mind, or have downloaded it already) + + +for ii=1:length(fn) + Obj=SOFAload(['db://database/tu-berlin (directivity)/' fn{ii}]); + + % % update dimensions to see if it works + % D=SOFAupdateDimensions(D, 'verbose',1); + + % plot the geometry because why not + SOFAplotGeometry(Obj); + + % move every figure a little to the right from previous one + H=gcf; + % if ~isoctave; if ii>1; movegui(H,[(H.Position(1)+(ii-1)*300) H.Position(2)]); end; end + if exist('OCTAVE_VERSION','builtin') == 0; if ii>1; movegui(H,[(H.Position(1)+(ii-1)*300) H.Position(2)]); end; end + + % set title + title(strrep(char(fn(ii)),'_',' ')); + disp([' Figure ' num2str(ii) ' of ' num2str(length(fn))+1 ' plotted: ' strrep(char(fn(ii)),'_',' ')]); +end + + +%% plot_trumpet_directivity +% original code from Fabian Brinkmann (12.2021), adapted by Michael Mihocic (2021-2022) +% requires AKp.m, check dependencies, otherwise skip this part +if exist('AKp.m', 'file') + + % load Data + H = SOFAload('db://database/tu-berlin%20(directivity)/Trumpet_modern_a4_fortissimo.sofa'); + + p = H.Data.Real(:,:,1) + 1j * H.Data.Imag(:,:,1); + p_log = 20*log10(p/max(abs(p))); + + % plot + AKf(20) + AKp(p_log, 'x2', 'g', H.ReceiverPosition(:, 1:2), 'dr', [-10 0], ... + 'hp_view', [30 45], 'cm', 'RdBu_flip', 'cb', 0, ... + 'sph_proc', 'interpSpline1'); + title '' + + AKtightenFigure; + disp(' Figure 3 of 3 plotted: Trumpet_modern_a4_fortissimo.sofa'); +else + warning(' Figure 3 of 3 skipped: Trumpet_modern_a4_fortissimo.sofa'); + disp(' To plot this figure you need to:'); + disp(' - download AKtools.zip (release) from: https://www.ak.tu-berlin.de/menue/publications/open_research_tools/aktools/'); + disp(' - extract the zip file'); + disp(' - run AKtoolsStart.m'); + disp(' - add the path of AKtoolsStart.m to Matlab (including subdirectories!)'); +end + +%% +disp(' '); +disp('### demo_FreeFieldDirectivityTF: done ###'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..8787ae7d5726992cded804cea54ee36f735dbd3e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRIR.m @@ -0,0 +1,64 @@ +% Demonstrates the usage of the FreeFieldHRIR conventions. + +% #Author: Michael Mihocic (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='FreeFieldHRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..45dda7fba262b69dae814e5f6ef76e19ecb19418 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_FreeFieldHRTF.m @@ -0,0 +1,268 @@ +% Demonstrates the usage of spherical harmonics (SH) for HRTF interpolation. +% demo_FreeFieldHRTF loads an HRTF set, transforms to TF, then to SH, then +% samples the horizontal and median plane in steps of 0.5 degrees. Finally, +% the files are saved in SOFAdbPath as demo_FreeFieldHRTF_{TF, SH, TFrec}.sofa. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: save figures as optional parameter added, figures are saved with respective titles as names (10.11.2021) +% #Author: Michael Mihocic: minor bugs fixed (28.12.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +savefigures=0; % save all created figures as fig and png (0: no, 1: yes) +if savefigures==1 + close all; % clean-up first + warning('off', 'MATLAB:MKDIR:DirectoryExists'); % suppress warning if folder exists + mkdir ([mfilename('fullpath') ' figures']); % output folder for figures + folder=[mfilename('fullpath') ' figures' filesep]; +end + +%% Let's start, load a SimpleFreeFieldHRIR SOFA object +IR=SOFAload('db://database/thk/HRIR_L2354.sofa'); +fs=IR.Data.SamplingRate; +IR.GLOBAL_APIVersion=SOFAgetVersion; +%% Figures +figure; +SOFAplotHRTF(IR,'magmedian'); +tit='SimpleFreeFieldHRIR (FIR, mag), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +% print([folder tit '.png'], '-dpng'); +end + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_1_IR.sofa'),IR); + +%% Convert to TF +TF=SOFAgetConventions('SimpleFreeFieldHRTF'); +TF.ListenerPosition=IR.ListenerPosition; +TF.ListenerPosition_Type=IR.ListenerPosition_Type; +TF.ListenerPosition_Units=IR.ListenerPosition_Units; +TF.ListenerView=IR.ListenerView; +TF.ListenerView_Type=IR.ListenerView_Type; +TF.ListenerView_Units=IR.ListenerView_Units; +TF.ListenerUp=IR.ListenerUp; +TF.SourcePosition=IR.SourcePosition; +TF.SourcePosition_Type=IR.SourcePosition_Type; +TF.SourcePosition_Units=IR.SourcePosition_Units; +TF.EmitterPosition=IR.EmitterPosition; +TF.EmitterPosition_Type=IR.EmitterPosition_Type; +TF.EmitterPosition_Units=IR.EmitterPosition_Units; +TF.ReceiverPosition=IR.ReceiverPosition; +TF.ReceiverPosition_Type=IR.ReceiverPosition_Type; +TF.ReceiverPosition_Units=IR.ReceiverPosition_Units; + +TF.Data.Real=zeros(IR.API.M,IR.API.R,IR.API.N+1); +TF.Data.Imag=zeros(IR.API.M,IR.API.R,IR.API.N+1); +for ii=1:IR.API.M + for jj=1:IR.API.R + sp=fft(squeeze(IR.Data.IR(ii,jj,:)),2*IR.API.N); % Delay not considered! + TF.Data.Real(ii,jj,:)=real(sp(1:IR.API.N+1,:)); + TF.Data.Imag(ii,jj,:)=imag(sp(1:IR.API.N+1,:)); + end +end +TF.N=(0:fs/2/IR.API.N:fs/2)'; + +TF=SOFAupdateDimensions(TF); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_2_TF.sofa'),TF); + +%% Plot median plane and horizontal planes for reference +figure; +SOFAplotHRTF(TF,'magmedian'); +tit='SimpleFreeFieldHRTF (TF, mag), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(TF,'etchorizontal'); +tit='SimpleFreeFieldHRTF (TF, etc), for reference'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% Convert to an emitter-based representation, TFE +TFE=TF; +TFE.GLOBAL_SOFAConventions = 'GeneralTF-E'; +TFE.GLOBAL_DataType = 'TF-E'; +TFE.API.E=TF.API.M; +TFE.API.M=1; +TFE.Data=rmfield(TFE.Data,{'Real','Imag'}); +TFE.Data.Real(1,:,:,:)=shiftdim(TF.Data.Real,1); % MRN --> 1RNM --> MRNE with M=1 +TFE.API.Dimensions.Data.Real='MRNE'; +TFE.Data.Imag(1,:,:,:)=shiftdim(TF.Data.Imag,1); +TFE.API.Dimensions.Data.Imag='MRNE'; +TFE.EmitterPosition=TF.SourcePosition; +TFE.EmitterPosition_Type=TF.SourcePosition_Type; +TFE.EmitterPosition_Units=TF.SourcePosition_Units; +TFE.API.Dimensions.EmitterPosition='ECI'; +TFE.SourcePosition=[0 0 0]; +TFE.API.Dimensions.SourcePosition='IC'; + +TFE=SOFAupdateDimensions(TFE); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_3_TFE.sofa'),TFE); + +%% Convert to SH +SH=TFE; +SH.GLOBAL_SOFAConventions = 'FreeFieldHRTF'; + +Lmax=floor(sqrt(size(SH.EmitterPosition,1))-1); % Max SH order +L=40; % actual SH order +[S, SH.API.E]=sph2SH(SH.EmitterPosition(:,1:2), L); + +Sinv=pinv(S); +SH.Data.Real=zeros(1, SH.API.R, SH.API.N, SH.API.E); +SH.Data.Imag=zeros(1, SH.API.R, SH.API.N, SH.API.E); +for ii=1:TFE.API.R + for jj=1:TFE.API.N + SH.Data.Real(1,ii,jj,:)=Sinv*squeeze(TFE.Data.Real(1,ii,jj,:)); + SH.Data.Imag(1,ii,jj,:)=Sinv*squeeze(TFE.Data.Imag(1,ii,jj,:)); + end +end + +SH.EmitterPosition=mean(SH.EmitterPosition); +SH.EmitterPosition_Type='Spherical Harmonics'; + +SH = SOFAupdateDimensions(SH); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_4_SH.sofa'),SH); + +%% plot median and horizonal planes - spatially continuous +figure; +SOFAplotHRTF(SH,'magmedian'); %title(''); +tit='FreeFieldHRTF (TFE, mag) in Spherical Harmonics'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(SH,'etchorizontal'); %title (''); +tit='FreeFieldHRTF (TFE, etc) in Spherical Harmonics'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot spatially continuous geometry +SOFAplotGeometry(SH); +tit='FreeFieldHRTF (TFE, geometry) in Spherical Harmonics'; % title +% if ~isoctave +if exist('OCTAVE_VERSION','builtin') == 0 + fig=gcf; + fig.Position(3:4)=[600,400]; % increase size (supported in Matlab only) +end +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot spatial spectra +figure; +for y=1:4 + subplot(2,2,y); hold on; + fax=0:fs/(2*SH.API.N):(fs-(fs/(2*SH.API.N)))/2; + r=1; plot(fax,20*log10(squeeze(abs(SH.Data.Real(1,r,:,y)+1i*SH.Data.Imag(1,r,:,y))))); + r=2; plot(fax,20*log10(squeeze(abs(SH.Data.Real(1,r,:,y)+1i*SH.Data.Imag(1,r,:,y)))),'r'); + xlabel('Frequency (Hz)'); + ylabel('Magnitude (dB)'); + tit=['SH spectra, coefficient index (ACN)= ' num2str(y)]; + title(tit); +end +subplot(2,2,1);legend('First receiver','Second receiver'); +if savefigures==1 + tit='SH spectra'; + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +%% plot all coefficients for a given frequency +figure; hold on; +f=10000; k=round(f/fs*2*SH.API.N); +plot(squeeze(20*log10(abs(SH.Data.Real(1,1,k,:)+1i*SH.Data.Imag(1,1,k,:)))),'ob'); +hold on; +plot(squeeze(20*log10(abs(SH.Data.Real(1,2,k,:)+1i*SH.Data.Imag(1,2,k,:)))),'xr'); +% title(); +xlabel('Coefficients (ACN index)'); +ylabel('Magnitude (dB)'); +legend('First receiver','Second receiver'); + +tit=['SH representation, frequency = ' num2str(f) ' Hz']; % title +title(tit); +if savefigures==1 + tit='SH representations'; % title + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + + +%% interpolate for the horizontal and median planes to FreeFieldHRTF (TFE) +TFEint=SH; +elemin=-90; +ele=[elemin:1:90 89:-1:elemin zeros(1,length(1:355))]'; +azi=[zeros(length(elemin:1:90),1); 180*ones(length(89:-1:elemin),1); (1:355)']; +radius=SH.EmitterPosition(:,3)*ones(size(ele)); +TFEint.EmitterPosition=[azi ele radius]; +TFEint.EmitterPosition_Type='spherical'; +TFEint.EmitterPosition_Units=SH.EmitterPosition_Units; +Sint = sph2SH(TFEint.EmitterPosition(:,1:2), L); +TFEint.API.E=size(Sint,1); +TFEint.Data.Real=zeros(1,2,TFEint.API.N,TFEint.API.E); +TFEint.Data.Imag=zeros(1,2,TFEint.API.N,TFEint.API.E); +for ii=1:TFEint.API.R + for jj=1:TFEint.API.N + TFEint.Data.Real(1,ii,jj,:)=Sint*squeeze(SH.Data.Real(1,ii,jj,:)); + TFEint.Data.Imag(1,ii,jj,:)=Sint*squeeze(SH.Data.Imag(1,ii,jj,:)); + end +end + +TFEint=SOFAupdateDimensions(TFEint); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_5_TFEint.sofa'),TFEint); + +%% interpolate for the horizontal and median planes to SimpleFreeFieldHRTF (TF) +TFint=TF; +ele=[-90:0.5:90 89:-.5:-90 zeros(1,length(1:0.5:355))]'; +azi=[zeros(length(-90:.5:90),1); 180*ones(length(89:-.5:-90),1); (1:0.5:355)']; +radius=1.2*ones(size(ele)); +TFint.SourcePosition=[azi ele radius]; +Sint = sph2SH(TFint.SourcePosition(:,1:2), sqrt(SH.API.E)-1); +TFint.API.M=size(Sint,1); +TFint.Data.Real=zeros(TFint.API.M,2,TFint.API.N); +TFint.Data.Imag=zeros(TFint.API.M,2,TFint.API.N); +for ii=1:TFint.API.R + for jj=1:TFint.API.N + TFint.Data.Real(:,ii,jj)=Sint*squeeze(SH.Data.Real(1,ii,jj,:)); + TFint.Data.Imag(:,ii,jj)=Sint*squeeze(SH.Data.Imag(1,ii,jj,:)); + end +end + +TFint=SOFAupdateDimensions(TFint); + +SOFAsave(fullfile(SOFAdbPath,'sofatoolbox_test','demo_FreeFieldHRTF_6_TFint.sofa'),TFint); + +%% compare +figure; +SOFAplotHRTF(TFint,'magmedian'); %title(''); +tit='SimpleFreeFieldHRTF (TF, mag), interpolated'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end + +figure; +SOFAplotHRTF(TFint,'etchorizontal'); % title(''); +tit='SimpleFreeFieldHRTF (TF, etc), interpolated'; % title +title(tit); +if savefigures==1 + saveas(gcf,[folder tit '.fig']); saveas(gcf,[folder tit '.png']); % save figures +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m new file mode 100644 index 0000000000000000000000000000000000000000..a2b7c1a87c9419df29865307eaac767c61d9cbfd --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_General.m @@ -0,0 +1,40 @@ +% Demonstrates the usage of the General conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='General'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.API.E=1; +Obj.Data.IR=rand(4800,1); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m new file mode 100644 index 0000000000000000000000000000000000000000..842ef389d8bc513bc908725e64c079fe3fd52acf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR.m @@ -0,0 +1,65 @@ +% Demonstrates the usage of the GeneralFIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='GeneralFIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] +Obj.Data.Delay=[0 0]; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m new file mode 100644 index 0000000000000000000000000000000000000000..9f9f9fc2086f540f73c0dcf7fa72dc4ac079e037 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralFIR_E.m @@ -0,0 +1,65 @@ +% Demonstrates the usage of the GeneralFIR-E conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='GeneralFIR-E'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill some data... +% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +% Create the impulse response +N=256; +IR=[zeros(100,1); 1; zeros(N-100-1,1)]; + +% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] +Obj.Data.Delay=[0 0]; + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m new file mode 100644 index 0000000000000000000000000000000000000000..bbe277b63ff5d6db5bd5b2081393f6ceabd5229b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF.m @@ -0,0 +1,43 @@ +% Demonstrates the usage of the GeneralTF conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +% clear; +conventions='GeneralTF'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.ReceiverPosition=[0,0.09,0]; +Obj.SourcePosition=[1,0,0;0,1,0;-1,0,0;0,-1,0]; +% Fill some random data +Obj.Data.Real=[-0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024]; +Obj.Data.Imag=[0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005]; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m new file mode 100644 index 0000000000000000000000000000000000000000..e9cdde7ca57add1f4cfa392b0df2653df3212c61 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_GeneralTF_E.m @@ -0,0 +1,45 @@ +% Demonstrates the usage of the GeneralTF-E conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +% clear; +conventions='GeneralTF-E'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.ReceiverPosition=[0,0.09,0]; +Obj.SourcePosition=[1,0,0;0,1,0;-1,0,0;0,-1,0]; +% Fill some random data +% Obj.Data.Real=[-0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024]; +% Obj.Data.Imag=[0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005; 0.0009, -0.0014, 0.0010, -0.0024; -0.0055, 0.0003, 0.0001, -0.0005]; +Obj.Data.Real=rand(4,4800); +Obj.Data.Imag=rand(4,4800); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[strrep(conventions,'-','_') '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..6190b9aa8b6b2d09a39f3dfd167dede77ac58be4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_LISTEN2SOFA.m @@ -0,0 +1,42 @@ +% load HRTF in LISTEN format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +if ~exist('subjectID','var'); subjectID='1002'; end +% File name of the LISTEN file +LISTENfile=['IRC_' subjectID '_C_HRIR']; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load LISTEN file +LISTENfn=fullfile(fileparts(SOFAdbPath),'LISTEN',['IRC_' subjectID],'COMPENSATED','MAT','HRIR',[LISTENfile '.mat']); +if isfile(LISTENfn) + disp(['Loading: ' LISTENfn]); + LISTEN=load(LISTENfn); +else + warning(['File not existing: ' LISTENfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath),'LISTEN',['IRC_' subjectID],'COMPENSATED','MAT','HRIR')]); + error(['Sorry.... ' mfilename ' cannot complete! The following file is missing: ' LISTENfile '.mat']); +end + +%% convert +Obj=SOFAconvertLISTEN2SOFA(LISTEN,subjectID); +Obj.GLOBAL_DatabaseName = 'LISTEN'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['LISTEN_' subjectID '_' LISTENfile '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..17bc908327b810b38c4bd17600fea728741b3a49 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MIT2SOFA.m @@ -0,0 +1,37 @@ +% load HRTF in MIT format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Two ears are available: normal and large. Select one or define before running this script. +if ~exist('pinna','var') + pinna='normal'; +end + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +MITfn=fullfile(fileparts(SOFAdbPath),'MIT KEMAR'); +disp(['Loading: ' MITfn ', pinna:' pinna]); + +%% load and convert +Obj=SOFAconvertMIT2SOFA(MITfn,pinna); +Obj.GLOBAL_DatabaseName = 'MIT'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['MIT_KEMAR_' pinna '_pinna.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..4a3ba286799a2c208ad7291b3f8db6b97e720dbb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_MultiSpeakerBRIR.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the MultiSpeakerBRIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='MultiSpeakerBRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill data... +Obj.Data.IR=rand(4800,2); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m new file mode 100644 index 0000000000000000000000000000000000000000..ac2b4ce34a757e3b5cad84d8552559b5a48fa1d9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_PlaySound.m @@ -0,0 +1,35 @@ +% SOFA Toolbox - test script +% Test audio playback after convolving sound file + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% put your information here: +hrtf = SOFAload('path/to_your/HRTF.sofa'); % Load your impulse response into a struct +soundInput = audioread('path/to_your/fancy_audio_file.wav'); % Load your sound file + +%% demo script +% Start SOFA +SOFAstart; +% Display some information about the impulse response +SOFAinfo(hrtf); +% Plot a figure with the measurement setup +SOFAplotGeometry(hrtf); +% Have a look at the size of the data +disp(['size [MxRxN]: ' num2str(size(hrtf.Data.IR))]) +% Calculate the source position from a listener point of view +apparentSourceVector = SOFAcalculateAPV(hrtf); +% Listen to the HRTF with azimuth of -90° +apparentSourceVector(91, 1) +SOFAplotGeometry(hrtf, 91); +soundOutput = [conv(squeeze(hrtf.Data.IR(91, 1, :)), soundInput) ... + conv(squeeze(hrtf.Data.IR(91, 2, :)), soundInput)]; +sound(soundOutput, hrtf.Data.SamplingRate); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..e9e7c2139b7e2bb83c4ff7605039acd8a54d488b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SCUT2SOFA.m @@ -0,0 +1,40 @@ +% load HRTF in MIT format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Two ears are available: normal and large. Select one. +pinna='normal'; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Define directory +SCUTdata = 'nearfield'; +SCUTroot=fullfile(fileparts(SOFAdbPath),'SCUT',SCUTdata); +disp(['Loading: ' SCUTroot]); + +%% Define radii for converting +radius=[0.2 0.25 0.3:0.1:1]; +% radius=0.2; + +%% load and convert +Obj=SOFAconvertSCUT2SOFA(SCUTroot,radius); +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + +%% save SOFA file +str=sprintf('%g,',radius); +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['SCUT_KEMAR_radius_' str(1:end-1) '.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m new file mode 100644 index 0000000000000000000000000000000000000000..24c31341b7cfb0a71f39d3632c4983b1ae78eea1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFA2ARI.m @@ -0,0 +1,42 @@ +% load HRTF in SOFA format and save as ARI format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% File name of the ARI file +ARIfile='hrtf_M_dtf 256'; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Load ARI file +ARIfn=fullfile(fileparts(SOFAdbPath), 'ARI', subjectID, [ARIfile '.mat']); +disp(['Loading: ' ARIfn]); +ARI=load(ARIfn); + +%% convert from ARI to SOFA +disp('Converting to SOFA...'); +Obj=SOFAconvertARI2SOFA(ARI.hM,ARI.meta,ARI.stimPar); + +%% convert back from SOFA to ARI +disp('Converting back to ARI (hM, meta, stimPar)...'); +[hM, meta, stimPar]=SOFAconvertSOFA2ARI(Obj); + +%% Calculate the differences +disp(['RMS difference between the new hM and the original ARI.hM: ' num2str(sum(sum(sqrt(mean((hM-ARI.hM).^2)))))]); +if sum(sum(sqrt(mean((hM-ARI.hM).^2))))>1, error('hM and ARI.hM not identic'); end +disp(['RMS difference between the new meta.pos and the original ARI.meta.pos: ' num2str(sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2))))]); +if sum(sqrt(mean((meta.pos(:,1:2)-ARI.meta.pos(:,1:2)).^2)))>1, error('meta.pos and ARI.meta.pos not identic'); end + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m new file mode 100644 index 0000000000000000000000000000000000000000..def227d2fdfaf56cb82e61da8b90515424cbf977 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAHRTF2DTF.m @@ -0,0 +1,69 @@ +% load HRTF and plots CTF and average DTF +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define parameters +% Subject index of the file to convert +subject=3; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'database', 'cipic', ['subject_' sprintf('%03d',subject) '.sofa']); +X=SOFAload(SOFAfn); + +if exist('OCTAVE_VERSION','builtin') + % We're in Octave + pkg load signal; % for 'shiftdata' compatibility +end + +[D,C]=SOFAhrtf2dtf(X); + +% close all; +f = figure; +set(f, 'Position', [50, 400, 1100, 500]); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,1,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(C.Data.IR(1,1,1:length(C.Data.IR)/2)))))); +data=(20*log10(abs(fft(squeeze(C.Data.IR(1,2,:)))))); +stepsize=C.Data.SamplingRate/length(data)*2; +plot(1:stepsize:C.Data.SamplingRate,data(1:length(data)/2)); +% ax=gca; set(ax,'XScale','log'); +hold on; grid on; + +[D,CC]=SOFAhrtf2dtf(D); + +subplot(1,2,1); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('left'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best') + +subplot(1,2,2); +% plot(20*log10(abs(fft(squeeze(CC.Data.IR(1,1,1:length(C.Data.IR)/2))))),'r'); +data=(20*log10(abs(fft(squeeze(CC.Data.IR(1,2,:)))))); +stepsize=CC.Data.SamplingRate/length(data)*2; +plot(1:stepsize:CC.Data.SamplingRate,data(1:length(data)/2),'r'); +title('right'); +xlabel('f (in Hz)'); ylabel('dB'); +legend('CTF','Avg DTF','Location','Best'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m new file mode 100644 index 0000000000000000000000000000000000000000..339e4f6f304ac45411108b227fd99fa9ba382e60 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateITD.m @@ -0,0 +1,43 @@ +% load HRTF and plots ITD + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. +% + +%% Define parameters +% Subject index of the file to convert +subject=3; + +%% load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'database', 'cipic', ['subject_' sprintf('%03d',subject) '.sofa']); +Obj=SOFAload(SOFAfn, 'nochecks'); + +%% Calculate Interaural time delay +[itd_time, ~, ~, Obj_time] = SOFAcalculateITD(Obj, 'time', 'thr', 20); +[itd_samples, ~, ~, Obj_samples] = SOFAcalculateITD(Obj, 'samples', 'thr', 20); + +%% Plot results +h = figure(); +subplot(211) +plot((Obj_time.Data.Delay(:,1) - Obj_time.Data.Delay(:,2))*1e6) +xlabel('Position') +ylabel('Time (\mus)') +axis tight + +subplot(212) +plot((Obj_samples.Data.Delay(:,1) - Obj_samples.Data.Delay(:,2))) +xlabel('Position') +ylabel(['Samples (Fs:' num2str(Obj.Data.SamplingRate), 'Hz)']) +axis tight + +%% Polar plot (not working in Octave) +SOFAplotHRTF(Obj, 'itdhorizontal'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m new file mode 100644 index 0000000000000000000000000000000000000000..806bf50201abc12048719d1f7687e500c6fb4fbb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAcalculateLFE.m @@ -0,0 +1,87 @@ +% load HRTF and extends low frequency content +% + +% #Author: Davi Carvalho +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. +% + +clear; % clc; close all; + +SOFAfile=fullfile(SOFAdbPath,'database','cipic','subject_003.sofa'); +Obj=SOFAload(SOFAfile); + + +%% Low frequency extension +fmin = 15; +fmax = 500; +Obj_lfe = SOFAcalculateLFE(Obj, fmin, fmax); + + +%% general properties +fs = Obj.Data.SamplingRate; +% HRIRs +IR = shiftdim(Obj.Data.IR, 2); +IR_lfe = shiftdim(Obj_lfe.Data.IR, 2); +% Number of samples +N = size(IR, 1); +N_lfe = size(IR_lfe, 1); +% Time vector +tx = 0:1/fs:(N-1)/fs; +tx_ext = 0:1/fs:(N_lfe-1)/fs; +% Frequency vector +freq = (0:N/2-1)*fs/N; +freq_lfe = (0:N_lfe/2-1)*fs/N_lfe; + + +%% PLOTS +ch = 1; % ear +pos = 100; % position index + +%%% Plot time +figure() +plot(tx, IR(:,pos,ch)); hold on +plot(tx_ext(1:N), IR_lfe(1:N, pos, ch), '--','linewidth', 1.3); hold off +legend('original', 'LFE', 'location', 'best') +xlabel('Time (ms)') +axis tight + +%%% Plot freq +figure() +ori = mag2db(abs(fft(IR(:,pos,ch), N_lfe))); +lfe = mag2db(abs(fft(IR_lfe(:,pos,ch)))); +semilogx(freq_lfe, ori(1:N_lfe/2)); hold on +semilogx(freq_lfe, lfe(1:N_lfe/2), '--','linewidth', 1.3); hold off +legend('original', 'LFE', 'location', 'best') +xlabel('Frequency (Hz)') +ylabel('Amplitude (dB)') +axis tight + +% %% Phase +% t = 0:1/1e3:10; +% fo = 0; +% f1 = 500; +% y = chirp(t,fo,t(end),f1,'linear',0,'complex'); +% figure +% semilogx(angle(fft(y))) +% title('phase') + +%% +figure +SOFAplotHRTF(Obj,'maghorizontal'); +figure +SOFAplotHRTF(Obj_lfe,'maghorizontal'); + + + + + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m new file mode 100644 index 0000000000000000000000000000000000000000..c3c196a6318ab79290729766c95bf02bc2c8e708 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAexpandcompact.m @@ -0,0 +1,55 @@ +% This demo shows how to use SOFAexpand and SOFAcompact +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Expanding the objects +x=whos('Obj'); +disp('Expanding the objects'); +tic; +clear Expanded +for ii=1:length(radius) + Expanded(ii)=SOFAexpand(Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Expanded'); +disp([' Expanded object array is now larger by ' num2str(round((y.bytes-x.bytes)/1024)) ' kb']); + +%% Compress the object +disp('Compressing the objects'); +tic; +clear Compacted +for ii=1:length(radius) + Compacted(ii)=SOFAcompact(Expanded(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +y=whos('Compacted'); +disp([' Compacted object array is now as small as the original one. Difference: ' num2str(round((x.bytes-y.bytes)/1024)) ' kb']); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m new file mode 100644 index 0000000000000000000000000000000000000000..79de42b828a2285512a4e65470b62b367526d969 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAload.m @@ -0,0 +1,78 @@ +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Path definitions +SOFAfile=fullfile(SOFAdbPath, 'database', 'tu-berlin', 'qu_kemar_anechoic_all.sofa'); + +%% Loading the full object +disp(['Loading full object: ' SOFAfile]); +tic; +ObjFull=SOFAload(SOFAfile); +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% Loading metadata +disp('Loading all metadata and partial data only'); +tic; +Meta=SOFAload(SOFAfile,'nodata'); + +%% Get index of measurements with the same directions +azi=0; ele=0; +idx=find(Meta.SourcePosition(:,1)==azi & Meta.SourcePosition(:,2)==ele); + +%% Load the parts of the full objects +disp('Loading partial data only'); +clear Obj +for ii=1:length(idx); + Obj(ii)=SOFAload(SOFAfile,[idx(ii) 1]); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('Obj'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Load parts of multiple dimensions of the full object +%e.g. only left ear for source positions 0�-90� at distance 1m +tic +idxSTART=find(Meta.SourcePosition(:,1)==0 & Meta.SourcePosition(:,3)==1); +idxEND=find(Meta.SourcePosition(:,1)==90 & Meta.SourcePosition(:,3)==1); +idxCOUNT=idxEND-idxSTART+1; +disp('Loading partial data in multiple dimensions') +ObjPartMultDim=SOFAload(SOFAfile,[idxSTART idxCOUNT],'M',[1 1],'R'); +disp([' Elapsed time: ' num2str(toc) ' s.']); +xobj=whos('ObjPartMultDim'); xmeta=whos('Meta'); +disp([' Memory requirements: ' num2str(round((xobj.bytes+xmeta.bytes)/1024)) ' kb']); + +%% Extract and plot the fully loaded data +IRsFull=squeeze(ObjFull.Data.IR(idx,1,:)); +legFull=num2str(ObjFull.SourcePosition(idx,3)); +subplot(1,2,1); +plot(IRsFull'); +legend(legFull); +title(['Demo of SOFAload:' 10 ... + 'Fully loaded data']); +xlabel(['Index (Sample Taps), fully loaded']); +ylabel('Amplitude'); + +%% Extract and plot the partially loaded data +IRs=zeros(length(idx), Obj(1).API.N); +for ii=1:length(idx) + IRs(ii,:)=squeeze(Obj(ii).Data.IR(:,1,:)); + leg{ii}=num2str(Obj(ii).SourcePosition(:,3)); +end +subplot(1,2,2); +plot(IRs'); +legend(leg); +title(['IRs for the left ear with radius as parameter' 10 ... + 'Partially loaded data']); +xlabel(['Index (Sample Taps), partially loaded']); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m new file mode 100644 index 0000000000000000000000000000000000000000..0e3e28d79a25de3493595ba324024ecc14aca15d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAmerge.m @@ -0,0 +1,64 @@ +% This demo shows how to use SOFAmerge +% It requires the TU-Berlin KEMAR HRTFs for different radii in the SOFA +% directory. These files can be generated by demo_TUBerlin2SOFA +% +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + + +%% Define parameters +% Prefix to the files +TUBfile = 'qu_kemar_anechoic_'; +% Define vector with radii to be merged. Available files: 0.5, 1, 2, and 3 m +radius=[0.5 1 2 3]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load the objects to be merged +clear Obj; +for ii=1:length(radius) + sourcefn=fullfile(SOFAdbPath, 'database', 'tu-berlin', [TUBfile num2str(radius(ii)) 'm.sofa']); + disp(['Loading: ' sourcefn]); + Obj(ii)=SOFAload(sourcefn); +end + +%% Merging the objects +disp('Merging to a single SOFA object'); +tic; +ObjFull=Obj(1); +for ii=2:length(radius) + ObjFull=SOFAmerge(ObjFull,Obj(ii)); +end +disp([' Elapsed time: ' num2str(toc) ' s.']); +x=whos('ObjFull'); +disp([' Memory requirements: ' num2str(round(x.bytes/1024)) ' kb']); + +%% save the object as a single SOFA file +warning('off','SOFA:save'); +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[TUBfile 'radius_' sprintf('%g_',radius) 'm.sofa']); +disp(['Saving: ' SOFAfn]); +tic; +Obj=SOFAsave(SOFAfn, ObjFull, compression); +x=whos('ObjFull'); +disp(['Saved ' num2str(round(x.bytes/1024)) ' kb in ' num2str(toc) ' s.']); + +%% Plot IRs for a single direction but different radius +azi=0; ele=0; +idx=find(Obj.SourcePosition(:,1)==azi & Obj.SourcePosition(:,2)==ele); +plot(squeeze(ObjFull.Data.IR(idx,1,:))'); +legend(num2str(ObjFull.SourcePosition(idx,3))) +title(['Demo of SOFAmerge:' 10 ... + 'IRs for the left ear with radius as parameter retrieved from a merged object']); +xlabel(' index (sample taps)'); +ylabel('Amplitude'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m new file mode 100644 index 0000000000000000000000000000000000000000..4650b0d87a738fa76b44c3d36f447cbc43cc7305 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotGeometry.m @@ -0,0 +1,64 @@ +% demo_SOFAplotGeometry - script demonstrating the usage of +% SOFAplotGeometry +% + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file in SimpleFreeFieldHRIR + +SOFAfile=fullfile(SOFAdbPath,'database','widespread','ICO1m_00139.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +% plot all measurements +SOFAplotGeometry(Obj); + +% % only show every 45th measurement +index = 1:45:Obj.API.M; +SOFAplotGeometry(Obj,index); + +% %% load a SingleRoomDRIR SOFA file +disp(['Loading: ' 'db://' fullfile('database','thk','DRIR_LBS_VSA_1202RS_SBL.sofa')]); +Obj=SOFAload(['db://' ... + fullfile('database','thk','DRIR_LBS_VSA_1202RS_SBL.sofa')]); + +% plot SOFA Object with 1202 Receivers +SOFAplotGeometry(Obj); + +% % remove all but one Receiver +Obj.ReceiverPosition = [0 0.09 0]; +Obj.ReceiverPosition_Type = 'cartesian'; +Obj.Data.IR = Obj.Data.IR(:,1,:); +Obj.Data.Delay = Obj.Data.Delay(:,1,:); +Obj = SOFAupdateDimensions(Obj); + +SOFAplotGeometry(Obj); + +% %% load a GeneralFIR SOFA file +SOFAfile=fullfile(SOFAdbPath,'database', 'tu-berlin','FABIAN_CTF_modeled.sofa'); +Obj = SOFAload(SOFAfile); + +SOFAplotGeometry(Obj); + +% %% load example with room geometry +disp(['Loading: ' SOFAfile]); +SOFAfile = fullfile(SOFAdbPath,'sofatoolbox_test', 'Oldenburg_OfficeII.sofa'); +Obj = SOFAload(SOFAfile); + +SOFAplotGeometry(Obj); + +% %% if exists try plotting SOFA file containing spherical harmonic emitter +% if exist(fullfile(SOFAdbPath,'demo_SHforHRTFs_SH.sofa')) +% Obj = SOFAload(fullfile(SOFAdbPath,'demo_SHforHRTFs_SH.sofa')); +% SOFAplotGeometry(Obj); +% else +% error('Run demoSHforHRTFS.m first.') +% end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m new file mode 100644 index 0000000000000000000000000000000000000000..c1813c46e700aaaa333861bfae06f8a3205648f5 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAplotHRTF.m @@ -0,0 +1,35 @@ +% demo_SOFAplotHRTF - script demonstrating the usage of SOFAplotHRTF + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file in SimpleFreeFieldHRIR +SOFAfile=fullfile(SOFAdbPath,'database','ari','dtf_nh2.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +% plot ETC horizontal plane +figure; +SOFAplotHRTF(Obj,'ETCHorizontal',1); +% plot magnitude spectrum in the median plane, channel 2 +figure; +SOFAplotHRTF(Obj,'MagMedian',2); + +%% load a GeneralTF SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari (sim)','hrtf_nh5_ref.sofa'); +Obj=SOFAload(SOFAfile); +% plot magnitude spectrum in the median plane, channel 1 +figure; +SOFAplotHRTF(Obj,'MagMedian',1); +figure; +SOFAplotHRTF(Obj,'MagMedian',1,'convert',0); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m new file mode 100644 index 0000000000000000000000000000000000000000..2d42da3d56b25a2fdb38ee4efde0e655959a645a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAsave.m @@ -0,0 +1,73 @@ +%% +% This demo creates an artificial HRTF set. +% It shows how to use SOFAgetConventions and SOFAsave +% The HRTF set contains single pulses placed at sample index of 100 +% which results in a broadband delay of 100 samples. +% Each IR is 256 samples long (i.e., N=256) + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Set parameters +% Latency of the created IRs +latency=100; % in samples, must be 1<latency<256 +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + + +%% Get an empy conventions structure +disp('Creating SOFA file with SimpleFreeFieldHRIR conventions...'); +Obj = SOFAgetConventions('SimpleFreeFieldHRIR'); + +%% Define positions - we use the standard CIPIC positions here +lat1=[-80 -65 -55 -45:5:45 55 65 80]; % lateral angles +pol1= -45 + 5.625*(0:49); % polar angles +pol=repmat(pol1',length(lat1),1); +lat=lat1(round(0.5:1/length(pol1):length(lat1)+0.5-1/length(pol1))); + +%% Create the impulse response +N=256; +IR=[zeros(latency,1); 1; zeros(N-latency-1,1)]; + +%% Fill data with data +M=length(lat1)*length(pol1); +Obj.Data.IR = NaN(M,2,N); % data.IR must be [M R N] + +ii=1; +for aa=1:length(lat1) + for ee=1:length(pol1) + Obj.Data.IR(ii,1,:)=IR; + Obj.Data.IR(ii,2,:)=IR; + [azi,ele]=hor2sph(lat(ii),pol(ii)); + Obj.SourcePosition(ii,:)=[azi ele 1]; + Obj.SourcePosition(ii,:)=[azi ele 1]; + ii=ii+1; + end +end + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'KEMAR'; +Obj.GLOBAL_History = 'created with a script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'piotr@majdak.com'; +Obj.GLOBAL_Comment = 'Contains simple pulses for all directions'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','Pulse.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m new file mode 100644 index 0000000000000000000000000000000000000000..e7a0f0cb9717ab4cdd58676e1d385e67d15b33af --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAspat.m @@ -0,0 +1,60 @@ +% SOFA Toolbox - demo script + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define the filename of the SOFA HRTFs +database='ari'; HRTFfilename='hrtf_nh4.sofa'; +% database='cipic'; HRTFfilename='subject_003.sofa'; +% database='listen'; HRTFfilename='irc_1002.sofa'; +% database='mit'; HRTFfilename='mit_kemar_normal_pinna.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_0.5m.sofa'; +% database='tu-berlin'; HRTFfilename='qu_kemar_anechoic_all.sofa'; + +%% Define the trajectory +azi=[-45 90 0]; % azimuth angles in degrees. If negative values are found, navigational system (-180;+180) will be used. +ele=[0 0 -30 90]; %elevation angles in degrees + +%% Load the HRTFs +fullfn=fullfile(SOFAdbPath, 'database', database, HRTFfilename); +disp(['Loading ' fullfn]); +Obj=SOFAload(fullfn); + +%% Create an input signal +in=randn(5*Obj.Data.SamplingRate,1); % Five seconds of noise +fade=round(0.02*Obj.Data.SamplingRate); % fade in and out for 20 ms +win=hanning(fade*2); +in(1:fade)=in(1:fade).*win(1:fade); +in(end-fade+1:end)=in(end-fade+1:end).*win(fade+1:end); +%% Spatialize +[out,azi,ele,idx]=SOFAspat(in,Obj,azi,ele); +disp('Binaural signal rendered'); + +%% Plot the trajectories +time = (1:length(azi))/Obj.Data.SamplingRate; + +figure +subplot(2,1,1); +plot(time,azi); % plot azimuthal trajectory +ylabel('Azimuth (deg)'); +title('SOFAspat: Trajectory'); + +subplot(2,1,2); +plot(time,ele); % plot elevational trajectory +ylabel('Elevation (deg)'); +xlabel('Time (s)'); + +%% Play the sound - use headphones! +if ~exist('dontplay','var'); + p=audioplayer(out, Obj.Data.SamplingRate); + play(p); +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m new file mode 100644 index 0000000000000000000000000000000000000000..1faddad111e737a2651fdc9af26073b9f598f2cf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAstrings.m @@ -0,0 +1,77 @@ +% Script for testing the string array feature of SOFA + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Test Strings as application-specific variable +% Load some arbritrary HRTFs +hrtf = SOFAload(fullfile(SOFAdbPath, 'database','ari','dtf_nh2.sofa')); +% Add a string array +str={}; +for ii=1:hrtf.API.M + str{ii,1}=['String' num2str(round(rand(1,1)*10000))]; +end +% SOFAaddVariable(Obj,Name,Dim,Value) +hrtf2 = SOFAaddVariable(hrtf,'Test','MS',str); +% Save as SOFA +SOFAsave('stringtest_applicationvar.sofa',hrtf2); +% Reload the file +hrtf = SOFAload('stringtest_applicationvar.sofa'); +% compare the strings +if prod(strcmp(hrtf.Test,hrtf2.Test)) + disp('SimpleFreeFieldHRIR: String Load-Reload: OK'); + delete('stringtest_applicationvar.sofa'); +else + error('String comparison showed differences'); +end +clear + + +%% Test with conventions GeneralString +% Create an empty object +Obj = SOFAgetConventions('GeneralString'); +% Create numeric data with M=15, R=2, N=10 +Obj.Data.Double=rand(15,2,10); +% Create string arrays +str2={}; str={}; +for ii=1:15 + id = num2str(round(rand(1,1)*1000000)); + str{ii,1}=['X' id]; + str2{ii,1}=['Left' id]; + str2{ii,2}=['Right' id]; +end +Obj.String2 = str2; % String1=[MRS] +Obj.Data.String1 = str; % Data.String1=[MS] +Obj.Data.String2 = str2; % Data.String2=[MRS] +% Add a new string with dimensions [RS] +strn={'left ear'; 'right ear'}; +Obj = SOFAaddVariable(Obj, 'Ears', 'RS', strn); +% Update dimensions +Obj = SOFAupdateDimensions(Obj); +% Save as SOFA +SOFAsave('stringtest_generalstring.sofa',Obj); +% Reload the file +Obj2 = SOFAload('stringtest_generalstring.sofa'); +% Compare the strings +if ~prod(strcmp(Obj2.Data.String2,Obj.Data.String2)) + error('Data.String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.String2,Obj.String2)) + error('String2: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.Data.String1,Obj.Data.String1)) + error('Data.String1: Comparison showed differences'); +end +if ~prod(strcmp(Obj2.Ears,Obj.Ears)) + error('Ears: Comparison showed differences'); +end +disp('GeneralString: String1, String2, Data, Ears: Load-Reload: OK'); +clear +delete('stringtest_generalstring.sofa'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m new file mode 100644 index 0000000000000000000000000000000000000000..5b0cff7487553798c5be7d70562fb365200952f4 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SOFAvariables.m @@ -0,0 +1,64 @@ +% SOFA Toolbox - script demonstrating the usage of variables in the API + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% load a SOFA file +SOFAfile=fullfile(SOFAdbPath,'database','ari','hrtf_nh5.sofa'); +disp(['Loading: ' SOFAfile]); +Obj=SOFAload(SOFAfile); + +%% read an API internal variable +M=Obj.API.M; % read M, the number of measurements +disp(['The number of measurements, M, is ' num2str(M)]); + +%% add a user-defined variable and check it + % create a random variable with the size M +myvar=rand(M,1); + % add to Obj +Obj=SOFAaddVariable(Obj,'MyVariable','M',myvar); + % check if it's there and identical to the created one +if ~all((Obj.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the size is M +if ~all(size(Obj.MyVariable)==[M 1]), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% add a private variable + % create a random variable with the size 1000 x 10 +privatevar=rand(1000,10); + % add to Obj as private +Obj=SOFAaddVariable(Obj,'MyVariable','Private',privatevar); + % check if it's there and identical to the created one +if ~all((Obj.PRIVATE.MyVariable-privatevar)<=eps('single')), error('Error!'); end + % check if the size is 1000 x 10 +if ~all(size(Obj.PRIVATE.MyVariable)==[1000 10]), error('Error!'); end + +%% Save the object + % create a random file name +fn=[mfilename '_temp_' num2str(rand(1,1)) '.sofa']; +SOFAsave(fn,Obj); + +%% Reload the object and remove the temporary file +Obj2=SOFAload(fn); +delete(fn); + +%% Check if the user-defined variable is still there +if ~isfield(Obj2,'MyVariable'), error('Error!'); end + % check if the size is M +if ~all(size(Obj2.MyVariable)==[M 1]), error('Error!'); end + % check if it is identical to the created one +if ~all((Obj2.MyVariable-myvar)<=eps('single')), error('Error!'); end + % check if the dimensions have been correctly stored +if ~strcmp(Obj2.API.Dimensions.MyVariable,'M'), error('Error!'); end + +%% Make sure that the private variable is not there! +if isfield(Obj2,'PRIVATE'), error('Error!'); end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m new file mode 100644 index 0000000000000000000000000000000000000000..4e6095731faf50a8eef000148949833aa5b822c9 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRIR2TF.m @@ -0,0 +1,108 @@ +% Convert data from SingleFreeFieldHRIR to SingleFreeFieldHRTF, +% extract a few frequency bins and save. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% #Author: Michael Mihocic: plot figures as optional parameter added, figures are saved with titles (10.11.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Subject index of the file to convert +subjectID='NH4'; +% HRTF or DTF? +ARIfile='hrtf'; +% Which frequency bins to store? +bins=[10, 20, 50, 70]; +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time +plotfigures=0; % 0: no figures; 1 show & save figures (and close others first) + +%% Load file in SimpleFreeFieldHRIR Conventions +f=filesep; +SOFAfn=fullfile(SOFAdbPath,'database','ari', [ARIfile '_' lower(subjectID) '.sofa']); + +if isfile(SOFAfn) + disp(['Loading: ' SOFAfn]); + IR=SOFAload(SOFAfn); +else + warning(['File not existing: ' SOFAfn ' --> Please download it from http://www.oeaw.ac.at/isf/hrtf and save it to: ' fullfile(SOFAdbPath,'database','ari', [ARIfile '_' lower(subjectID) '.sofa'])]); + error(['Sorry.... ' mfilename ' cannot complete!']); +end + +%% Plot figures +if plotfigures==1 + close all; + PlotFigures(IR, 'HRIR', '') +end + +%% Get a new SimpleFreeFieldTF conventions +TF=SOFAgetConventions('SimpleFreeFieldHRTF'); +disp('Converting SimpleFreeFieldHRIR to SimpleFreeFieldHRTF'); + +%% Copy variables and metadata +TFempty=rmfield(TF,fieldnames(SOFAgetConventions('SimpleFreeFieldHRTF','r'))); % skip all read-only metadata +Xf=fieldnames(rmfield(TFempty,{'API','Data'})); % skip other internal +for ii=1:length(Xf) + if isfield(IR, (Xf{ii})), TF.(Xf{ii})=IR.(Xf{ii}); end % copy if available +end + +%% Transform data +TF.Data.Real=zeros(IR.API.M,IR.API.R,length(bins)); +TF.Data.Imag=zeros(IR.API.M,IR.API.R,length(bins)); +TF.N=(bins*IR.Data.SamplingRate/IR.API.N)'; + +for ii=1:IR.API.M + cplx=fft((IR.Data.IR(ii,:,:))); + TF.Data.Real(ii,:,:)=real(cplx(:,:,bins)); + TF.Data.Imag(ii,:,:)=imag(cplx(:,:,bins)); +end + +%% Update dimensions +TF=SOFAupdateDimensions(TF); +%% Plot figures +if plotfigures==1 + PlotFigures(TF, 'HRTF', [', bins ' num2str(bins)]) +end + +%% Save +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',['ARI_' ARIfile '_' subjectID '_' num2str(length(bins)) '_freqs.sofa']); +disp(['Saving: ' SOFAfn]); +SOFAsave(SOFAfn,IR,compression); + +function PlotFigures(data, type, bins) + figure; SOFAplotHRTF(data,'EtcHorizontal'); % energy-time curve in the horizontal plane (+/- THR) + tit=[type ' ETC Horizontal' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'EtcMedian'); % energy-time curve in the median plane (+/- THR) + tit=[type ' ETC Median' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'MagHorizontal'); % magnitude spectra in the horizontal plane (+/- THR) + tit=[type ' Magnitude Horizontal' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures + figure; SOFAplotHRTF(data,'MagMedian'); % magnitude spectra in the median plane (+/- THR) + tit=[type ' Magnitude Median' bins]; % title + title(tit); + saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'MagSpectrum'); % single magnitude spectrum for direction(s) DIR in COLOR +% tit=[type ' Magnitude Spectrum' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'MagSagittal'); % magnitude spectra in a sagittal plane specified by OFFSET +/- THR +% tit=[type ' Magnitude Sagittal' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +% figure; SOFAplotHRTF(data,'ITDhorizontal'); % ITD horizontal +% tit=[type ' ITD Horizontal' bins]; % title +% title(tit); +% saveas(gcf,[tit '.fig']); saveas(gcf,[tit '.png']); save figures +end \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m new file mode 100644 index 0000000000000000000000000000000000000000..af290e211e94c02bedd37e62fcded6bc515f8727 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldHRSOS.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the SimpleFreeFieldHRSOS conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SimpleFreeFieldHRSOS'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.SOS=rand(4800,2,6); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m new file mode 100644 index 0000000000000000000000000000000000000000..8db35f584dcc52c4a9e119a84e6c5cce6c0be784 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleFreeFieldSOS.m @@ -0,0 +1,39 @@ +% Demonstrates the usage of the SimpleFreeFieldSOS conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SimpleFreeFieldSOS'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.SOS=rand(4800,2,6); + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m new file mode 100644 index 0000000000000000000000000000000000000000..91b10fdf6ae444f9cafecff94c79f76e000f0391 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SimpleHeadphoneIR.m @@ -0,0 +1,60 @@ +% SOFA Toolbox - demo script for the convention SimpleHeadphoneIR. +% load headphone IRs from a SOFA file from the ARI headphones database + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Define parameters +% Subject index of the file to convert +subjectID='NH5'; + +%% Load SOFA file +SOFAfn=fullfile(SOFAdbPath, 'headphones', 'ari', ['hpir_' lower(subjectID) '.sofa']); +disp(['Loading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot amplitude spectra +figure; +hold on; box on; +cols='bgrmky'; + +%if ~isoctave +if exist('OCTAVE_VERSION','builtin') == 0 + if isfield(X, 'MeasurementDate') + meastime=[0; diff(X.MeasurementDate)]; % diff not working in Octave + else + meastime=diff(X.GLOBAL_DateCreated); % diff not working in Octave + end +end + +for ii=1:X.API.M + plot(20*log10(abs(fft(squeeze(X.Data.IR(ii,1,:)),X.Data.SamplingRate))),cols(ii)); + if ii>1 + % if ~isoctave; + if exist('OCTAVE_VERSION','builtin') == 0 + leg{ii}=['#' num2str(ii) ':' num2str(meastime(ii)) ' seconds later']; + else + leg{ii}=['#' num2str(ii)]; + end + end +end + +for ii=1:X.API.M + plot(20*log10(abs(fft(squeeze(X.Data.IR(ii,2,:)),X.Data.SamplingRate)))-20,cols(ii)); +end + +xlim([-200 18200]); + +axis([-200 18200 -65 15]); +leg{1}='#1, first measurement'; +legend(leg); + + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m new file mode 100644 index 0000000000000000000000000000000000000000..5897b2feee3b844f811972058b9310ebd115e9da --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomDRIROldenburg.m @@ -0,0 +1,157 @@ +% demo for SingleRoomDRIR: save DRIR data from Uni Oldenburg (Office II) as +% SOFA file and plot the speaker and listener positions. +% It uses conventions SingleRoomDRIR and RoomType 'shoebox', defined by +% RoomCornerA and RoomCornerB. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% Based on the bachelor thesis of Wolfgang Hrauda (2013). + +% Measurement situation: +% T_60 = 300 ms +% speaker positions: +% entrance, desk, desk, at window (A, B, C, D) +% conditions: +% for position A and D: door and window were open +% Listener: headorientation = {1 2} -> 0�/-90� (straight/looking over right shoulder) +% Receivers: +% ch 1 & 2: 'in-ear' IRs from in-ear microphoes (not available for Office I) +% 'bte' 6-channel BTE-IRs: +% ch 3 & 4: 'front' BTE-IRs front microphone pair +% ch 5 & 6: 'middle' BTE-IRs middle microphone pair +% ch 7 & 8: 'rear' BTE-IRs rear microphone pair +% ambient noise: telepohne, keyboard typing, ventilation (all for both +% orientations); opening and closing the door (15 times) + + +%% Define parameters + + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% --- loading Uni Oldenburg data ---- +PathO=fullfile(fileparts(SOFAdbPath), 'Oldenburg','HRIR_database_mat','hrir','office_II'); +disp(['Loading from: ' PathO filesep]); + +A1fn = [PathO filesep 'office_II_1_A.mat']; +B1fn = [PathO filesep 'office_II_1_B.mat']; +C1fn = [PathO filesep 'office_II_1_C.mat']; +D1fn = [PathO filesep 'office_II_1_D.mat']; +A2fn = [PathO filesep 'office_II_2_A.mat']; +B2fn = [PathO filesep 'office_II_2_B.mat']; +C2fn = [PathO filesep 'office_II_2_C.mat']; +D2fn = [PathO filesep 'office_II_2_D.mat']; + +% has dimension: N x R +if isfile(A1fn); A1 = load(A1fn); else, error(['File not existing: ' A1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); B1 = load(B1fn); else, error(['File not existing: ' B1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); C1 = load(C1fn); else, error(['File not existing: ' C1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); D1 = load(D1fn); else, error(['File not existing: ' D1fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); A2 = load(A2fn); else, error(['File not existing: ' A2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); B2 = load(B2fn); else, error(['File not existing: ' B2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); C2 = load(C2fn); else, error(['File not existing: ' C2fn ' --> Please download it to: ' PathO filesep]); end +if isfile(A1fn); D2 = load(D2fn); else, error(['File not existing: ' D2fn ' --> Please download it to: ' PathO filesep]); end +% +% B1 = load([PathO filesep 'office_II_1_B.mat']); +% C1 = load([PathO filesep 'office_II_1_C.mat']); +% D1 = load([PathO filesep 'office_II_1_D.mat']); +% A2 = load([PathO filesep 'office_II_2_A.mat']); +% B2 = load([PathO filesep 'office_II_2_B.mat']); +% C2 = load([PathO filesep 'office_II_2_C.mat']); +% D2 = load([PathO filesep 'office_II_2_D.mat']); + +%% Get an empy conventions structure +Obj = SOFAgetConventions('SingleRoomDRIR'); + +%% Listener and Receiver +Obj.ReceiverPosition = [0 0.09 0; 0 -0.09 9; ... % in-ear + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % front bte + 0.02 0.09 0.02; 0.02 -0.09 0.02; ... % middle bte + 0.02 0.09 0.02; 0.02 -0.09 0.02]; % rear bte +Obj.ListenerPosition = [2.16 4.4 1.1]; +Obj.ListenerUp = [0 0 1]; +Obj.ListenerView = [repmat([1 0 0],4,1); repmat([0 -1 0],4,1)]; + +%% Source and Transmitter + +Obj.EmitterPosition = [0 0 0]; +A = [0.52 5.27 1.8]; +B = [0.79 1.25 1.1]; +C = [2.52 1.23 1.1]; +D = [2.38 0 1.8]; +Obj.SourcePosition = [A; B; C; D; A; B; C; D;]; +Av = [-1 0 0]; +Bv = [1 0 0]; +Cv = [1 0 0]; +Dv = [1 0 0]; +Obj.SourceView = [Av; Bv; Cv; Dv; Av; Bv; Cv; Dv;]; +Obj.SourceUp = [0 0 1]; + +%% Fill Data with data +% change data matrix dimension: N x R -> M x R x N +A1.data = shiftdim(A1.data,1); +data(1,:,:) = A1.data; +B1.data = shiftdim(B1.data,1); +data(2,:,:) = B1.data; +C1.data = shiftdim(C1.data,1); +data(3,:,:) = C1.data; +D1.data = shiftdim(D1.data,1); +data(4,:,:) = D1.data; +A2.data = shiftdim(A2.data,1); +data(5,:,:) = A2.data; +B2.data = shiftdim(B2.data,1); +data(6,:,:) = B2.data; +C2.data = shiftdim(C2.data,1); +data(7,:,:) = C2.data; +D2.data = shiftdim(D2.data,1); +data(8,:,:) = D1.data; +Obj.Data.IR = data; +Obj.Data.Delay = zeros(1,size(Obj.Data.IR,2)); +Obj.Data.SamplingRate = A1.fs; + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'HATS'; +Obj.GLOBAL_History='Converted from the Uni Oldenburg database'; +Obj.GLOBAL_License='http://medi.uni-oldenburg.de/hrir/html/download.html'; +Obj.GLOBAL_References='H. Kayser, S. D. Ewert, J. Anem�ller, T. Rohdenburg, V. Hohmann, and B. Kollmeier, "Database of Multichannel In-Ear and Behind-the-Ear Head-Related and Binaural Room Impulse Responses," EURASIP Journal on Advances in Signal Processing, vol. 2009, doi:10.1155/2009/298605'; + +%% Setup the room +Obj.GLOBAL_RoomType='shoebox'; +Obj.GLOBAL_RoomDescription='Office II at the University of Oldenburg, T_60 = 300 ms'; + +Obj.RoomCornerA = [0; 0; 0]; +Obj.RoomCornerA_Type = 'cartesian'; +Obj.RoomCornerA_Units = 'meter'; +Obj.API.Dimensions.RoomCornerA='C'; + +Obj.RoomCornerB = [3.3; 6; 0]; +Obj.RoomCornerB_Type = 'cartesian'; +Obj.RoomCornerB_Units = 'meter'; +Obj.API.Dimensions.RoomCornerB='C'; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Save SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test','Oldenburg_OfficeII.sofa'); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj, compression); +clear Obj; + +%% Re-load the file +disp(['Reloading: ' SOFAfn]); +X=SOFAload(SOFAfn); + +%% Plot the 2D-plan of the measurement setup +SOFAplotGeometry(X); +title('Office II from Kayser et al. (2009) saved as SingleRoomDRIR'); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..ab2bc5b033346bede970c2e444fbd4087254a00d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomMIMOSRIR.m @@ -0,0 +1,101 @@ +% Demonstrates the usage of SingleRoomMIMOSRIR. +% Idea: demo_SingleRoomMIMOSRIR loads SRIRs from ???, +% converts to SH as SingleRoomMIMOSRIR, does planewave decompositon, and stores +% the data as a ???.sofa file. + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Data +% https://phaidra.kug.ac.at/view/o:104376, LS: 3 oder 5 +% documentation: https://www.mdpi.com/2076-3417/10/11/3747 + +% Download IR dataset from https://phaidra.kug.ac.at/view/o:104376 +% Copy the folder 'LigetiHall_CubeletToSt450' to your current working directory + +Obj = SOFAgetConventions('SingleRoomMIMOSRIR'); +Obj.GLOBAL_Title = 'LigetiHall_CubeletToSt450'; +Obj.GLOBAL_Organization = 'Institut f�r elektronische musik und akustik, Graz, Austria'; +Obj.GLOBAL_AuthorContact = 'julien.demuynke@eurecat.org, markus.zaunschirm@atmoky.com, zotter@iem.at'; +Obj.GLOBAL_References = 'Auralization of High-Order Directional Sources from First-Order RIR Measurements (2020)'; +Obj.GLOBAL_Comment = '1rst order RIR measurements with Cubelet loudspeaker array protoype (6 loudspeakers) and TSL ST450 microphone (4 channels) in the György Ligeti Saal, Graz, Austria. The source was surrounded by 4 reflecting baffles (0.9 x 1.8 m) in its rear halfspace.'; +Obj.GLOBAL_ListenerShortName = 'TSL ST450'; +Obj.GLOBAL_SourceShortName = 'Cubelet loudspeaker array protoype'; +Obj.GLOBAL_DatabaseName = 'LigetiHall_CubeletToSt450_1rst_order_RIR'; +Obj.GLOBAL_ListenerDescription = ' 4-channel Ambisonic B-format microphone array with r = 2 cm'; +Obj.GLOBAL_SourceDescription = ' Spherical (r = 7.5 cm) 6-channel loudspeaker array prototype with loudspeakers arranged on surfaces of a cube'; +Obj.GLOBAL_RoomDescription = 'György-Ligeti Room in building LG14 - MUMUTH in Universität für Musik und darstellende Kunst Graz, Austria. Shoebox shaped room of surface 511.15m2 and volume 5630m3 with floor made of wooden panels'; + +Obj.ReceiverPosition_Type = 'spherical harmonics';%B-format +Obj.EmitterPosition = [0 0 0.075;90 0 0.075;180 0 0.075;270 0 0.075;0 90 0.075;0 -90 0.075]; +Obj.SourcePosition = [4.2 0 0]; +Obj.SourceView = [-1 0 0];%The source and the listener are facing each other + +addpath('./LigetiHall_CubeletToSt450/'); +IR_list = dir('./LigetiHall_CubeletToSt450/*.wav'); +if isempty(IR_list) + error([' Folder does not exist or is empty: ' cd filesep 'LigetiHall_CubeletToSt450.' newline ' Download IR dataset from https://phaidra.kug.ac.at/view/o:104376 and copy the folder ''LigetiHall_CubeletToSt450'' to your current working directory.']) +% error([' Folder does not exist or is empty: ' mfilename('fullpath') filesep 'LigetiHall_CubeletToSt450. Download IR dataset from https://phaidra.kug.ac.at/view/o:104376 and copy the folder ''LigetiHall_CubeletToSt450'' to your current working directory.']) +end +IR_INFO = audioinfo([IR_list(1).folder filesep IR_list(1).name]); + +C = 3; +I = 1; +M = 1; +R = IR_INFO.NumChannels; +N = IR_INFO.TotalSamples; +E = length(IR_list); + +fs = IR_INFO.SampleRate; +Obj.Data.IR = zeros(M,R,N,E); +for i = 1:6 + IR = audioread([IR_list(i).folder filesep IR_list(i).name]); + Obj.Data.IR(1,:,:,i) = transpose(IR); +end +Obj.Data.SamplingRate = fs; +Obj.Data.Delay = zeros(M,R,E); + +Obj.ReceiverView = zeros(R,C,I); +Obj.ReceiverUp = zeros(R,C,I); +Obj.EmitterView = zeros(E,C,I); +Obj.EmitterUp = zeros(E,C,I); + +Obj = SOFAupdateDimensions(Obj); +SOFAsave('LigetiHall_CubeletToSt450_IRs.sofa',Obj,0); +disp(['SOFA file saved to: ' pwd filesep 'LigetiHall_CubeletToSt450_IRs.sofa']); + +% +% Paper for the algorithms: +% Park, M. and Rafaely, B. (2005). "Sound-field analysis by plane-wave decomposition using spherical microphone array," +% JASA, 118, 3094�3103. https://doi.org/10.1121/1.2063108 + + + +%% Story line... +% First, the coefficients pnm up to order N are calculated using Eq. 5, + +% pnm = sum j=1 to M, a_j p(omega_j) Yn m_j. + + +% and then the waves directional amplitude +% density at each frequency, i.e., plane-wave decomposition, is +% computed at the desired directions using Eq. 9. +% +% b_n (kr,ka) = 4pi i^n(j_n(kr) ? ...) Eq. 7 +% +% w (omega_l) = sum n=0 to N sum m=?n to n p_nm / b_n Y (omega_l) + +% to be saved: p_nm and b_n(kr,ka) or simple a. +% + +%% Also this might help: Khaykin, D. and Rafaely, B. (2012). "Acoustic analysis by spherical +% microphone array processing of room impulse responses," JASA, 132, 261�270. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m new file mode 100644 index 0000000000000000000000000000000000000000..6504026c788ce3050333c90c8b58d8b87de4f4c8 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_SingleRoomSRIR.m @@ -0,0 +1,41 @@ +% Demonstrates the usage of the SingleRoomSRIR conventions. + +% #Author: Michael Mihocic +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - demo script +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or – as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +%% Get an empy conventions structure +clear; +conventions='SingleRoomSRIR'; +disp(['Creating SOFA file with ' conventions 'conventions...']); +Obj = SOFAgetConventions(conventions); + +%% Fill random data... +Obj.Data.IR=rand(4800,1); +Obj.ListenerPosition=zeros(4800,3); Obj.ListenerPosition(:,1)=1; +Obj.SourcePosition=zeros(4800,3); Obj.SourcePosition(:,2)=1; + +%% Update dimensions +Obj=SOFAupdateDimensions(Obj); + +%% Fill with attributes +Obj.GLOBAL_ListenerShortName = 'dummy'; +Obj.GLOBAL_History = 'created with a demo script'; +Obj.GLOBAL_DatabaseName = 'none'; +Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; +Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); +Obj.GLOBAL_Organization = 'Acoustics Research Institute'; +Obj.GLOBAL_AuthorContact = 'michael.mihocic@oeaw.ac.at'; + +%% save the SOFA file +SOFAfn=fullfile(SOFAdbPath,'sofatoolbox_test',[conventions '.sofa']); +disp(['Saving: ' SOFAfn]); +Obj=SOFAsave(SOFAfn, Obj); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m new file mode 100644 index 0000000000000000000000000000000000000000..58ce22adf7e6eabd7ee456bb6df95d0047691069 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/demos/demo_TUBerlin2SOFA.m @@ -0,0 +1,62 @@ +% SOFA Toolbox - demo script + +% load HRTF in TU Berlin format and save as SOFA format + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: bugs fixed (10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) + +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +%% Define parameters +% Prefix to the files +TUBfile = 'QU_KEMAR_anechoic_'; +% Define vector with radii to be loaded. Available files: 0.5, 1, 2, and 3 m +% radius=[0.5 1 2 3]; +radius=[0.5]; + +% Data compression (0..uncompressed, 9..most compressed) +compression=1; % results in a nice compression within a reasonable processing time + +%% Load, convert, and save the requested TU-Berlin files +for ii=1:length(radius) + % load + + TUBfn=fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR', [TUBfile num2str(radius(ii)) 'm.mat']); + + if isfile(TUBfn) + disp(['Loading: ' TUBfn]); + TUB=load(TUBfn); + else + if radius(ii) == 0.5 % catch if file name ends with "05m.mat" instead of "0.5m.mat" + TUBfn2=fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR', [TUBfile '05m.mat']); + if isfile(TUBfn2) + disp(['Loading: ' TUBfn2]); + TUB=load(TUBfn2); + else + warning(['File not existing: ' TUBfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR')]); + error(['Sorry.... ' mfilename ' cannot complete!']); + end + else + warning(['File not existing: ' TUBfn ' --> Please download it to: ' fullfile(fileparts(SOFAdbPath), 'TU-Berlin KEMAR')]); + error(['Sorry.... ' mfilename ' cannot complete!']); + end + end + + % convert and add application specific metadata + Obj=SOFAconvertTUBerlin2SOFA(TUB.irs); + Obj.GLOBAL_DatabaseName = 'TU-Berlin'; % maybe setting the name by function parameter + Obj.GLOBAL_ApplicationName = 'Demo of the SOFA Toolbox'; + Obj.GLOBAL_ApplicationVersion = SOFAgetVersion('API'); + Obj.GLOBAL_Organization = 'Technische Universit�t Berlin'; + Obj.GLOBAL_AuthorContact = 'hagen.wierstorf@tu-berlin.de'; + % save + SOFAfn=fullfile(SOFAdbPath, 'sofatoolbox_test', ['TU-Berlin_' TUBfile 'radius_' sprintf('%g',radius(ii)) 'm.sofa']); + disp(['Saving: ' SOFAfn]); + Obj=SOFAsave(SOFAfn, Obj, compression); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/history.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/history.txt new file mode 100644 index 0000000000000000000000000000000000000000..1e59e556fea7b6b8d8f33d5c587a8c9bb4576b7b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/history.txt @@ -0,0 +1,360 @@ +************************************************************* +*** History of SOFA Toolbox for Matlab and Octave +*** Acoustics Research Institute, Austrian Academy of Sciences, Vienna +*** Project leader: Piotr Majdak, piotr.majdak@oeaw.ac.at +*** Contributors: +*** Michael Mihocic +*** Harald Ziegelwanger +*** Hagen Wierstorf +*** Wolfgang Hrauda +*** Fabian Brinkmann +*** Felix Perchfler +************************************************************* + +*** DEVELOPMENT STATUS *** + +*** v2.1 (first 2.x release) + + +*** v2.0 (not released, rebranded to SOFA Toolbox) + +## Rebranding ## +- main directory renamed to "SOFAtoolbox" +- repository renamed to "SOFAtoolbox" +- all SOFA files created by demo_ will be saved in sofatoolbox_test + +## Core Functionality ## +- .gitignore added, updated multiple times +- Support for spherical harmonics added. +- SOFAconvertCoordinates.m: type horizontal-polar removed (not (properly) defined in SOFA) +- SOFAarghelper: minor bugs fixed (changes FB) +- SOFAinfo: showing all global mandatory fields now, plus some more for SimpleFreeFieldHRIR +- demoPlaySound.m added +- Readme.md: Example fixed (demoPlaySound.m) +- headers of functions checked, updated, author format changed to machine-readable format (#author) +- NETCDFload: 'deblank' command added when loading strings to avoid trailing empty spaces in size of array dimension +- SOFAcalculateITD.m added (adapted from AMT) +- SOFAcalculateLFE.m added (by DC), db changed to mag2db (Octave support) +- SOFAstart: + - Bug fixed when using 'restart' option: SOFAdbPath and SOFAdbURL were not reset + - Bug in help comment fixed + - flag 'full' added: show all information, including all compiled conventions & versions + - changed order of display output messages ((c) first) + - Bug fixed when adding paths (added at bottom in some specific cases) + +## Toolbox Functionality +- Conventions: + - Conventions for SOFA 2.0 added + - SOFAgetConventions: Versioning of convention files .CSV added + - csv files renamed to always include SOFAConventionsVersion in file name (created .mat files are unaffected) + - FreeFieldDirectivityTF_1.0.csv: + - updated by David Ackermann (not sure if ReceiverPosition and EmitterPosition still need to be updated) + - Mandatory flag removed for: Global:Comment, ListenerUp, ListenerUp:Type, ListenerUp:Units + - Dimension of ReceiverPosition and EmitterDescription fixed + - FreeFieldHRTF_1.0.csv: GLOBAL:SOFAConventionsVersion version number fixed + - SingleRoomSRIR_1.0.csv: GLOBAL:SOFAConventionsVersion version number fixed, RoomCornerA, RoomCornerB, RoomCorners:Type, RoomCorners:Units: Mandatory flag removed + - Dimension of Data.SamplingRate fixed to "I, M" for: GeneralFIR-E_2.0.csv, GeneralFIR_2.0.csv, General_1.0.csv, SimpleFreeFieldHRIR_1.0.csv, SimpleFreeFieldHRSOS_1.0.csv, SimpleHeadphoneIR_1.0.csv, SingleRoomSRIR_1.0.csv + - Conventions2Wiki.m: Column headers flags and dimensions changed to a hyperlink linking to that corresponding part on the website + - several bugs fixed; non-ASCII quotes replaced by ' (changes FB) + - Conventions FreeFieldHRIR_1.0.csv added + - SOFAcompileConventions: + - ignores files beginning with '_' + - Bug fixed when running in Octave + - '10' replaced by 'newline' in strings to avoid warnings in Octave + - display messages changed to output variable dispOutput + - bug fixed: replaced version "2" by "2.0" to keep one minor digit everywhere + - flags fixed +- Demos: + - demo_FreeFieldHRTF.m added; updated several times, allows saving figures as fig & png (see parameter 'savefigures'), some bug fixes + - demo_FreeFieldDirectivityTF.m: adapted to actual data on sofaconventions.org -> working now; plot_trumpet_directivity included + - SOFAconvertMIT2SOFA.m, demo_FHK2SOFA.m, demo_SingleRoomDRIROldenburg.m, demo_SingleRoomMIMOSRIR.m, demo_TUBerlin2SOFA.m: error message if source files are not available + - demo_ARI2SOFA.m, demo_LISTEN2SOFA.m: bug fixed: subject_ID was always overwritten; error message if source files are not available + - demo_SimpleFreeFieldHRIR2TF.m: bug fixed: Object to be saved was wrong; error message if source files are not available; updated several times; parameter 'plotfigures' causes plotting all figures, and saving them (fig, png) if set to 1 + - demo_SimpleHeadphoneIR.m: if .MeasurementDate is not existing use .GLOBAL_DateCreated as measurement time (legend in figure) + - SOFAconvertSCUT2SOFA.m: bug fixed when source files are not available -> error message + - demo_BTDEI2SOFA.m: Minor bug fixed in error message text + - demo_SOFAcalculateITD.m, demo_SOFAcalculateLFE.m added (by DC) + - demo_SphericalHarmonicsMic added +- test_SOFAall.m: + - structured (first *->SOFA, then SOFA->*, then SOFA functions, then SOFA conventions), and sorted (alphabetically) + - missing demos added + - disp messages improved + - some bugs fixed; all conventions are included in at least one demo file; all demos are tested with Matlab & Octave (run test_SOFAall.m) + - Matlab: all demos are working in Matlab, without any visible warnings + - Octave: all demos are working without any errors except for FHK2SOFA (not working at all; skipped in Octave), and some minor restrictions cause by unsupported commands, see warning messages during process for details + - some bugs fixed; demos that require souce files that are not publicly available will be catched with a warning instead of an error +- Download links updated for: + - HRTFs\ARI\readme.txt + - HRTFs\CIPIC\readme.txt + - HRTFs\TU-Berlin KEMAR\readme.txt +- SOFAplotHRTF: + - 'convert' flag added -> 1: convert to FIR and then to TF domain. Can be set to 0 if data is available in TF domain (FreeFieldDirectivityTF, GeneralTF, SimpleFreeFieldHRTF conventions). By default the function chooses the best option. + - type 'ITDhorizontal' added (changes DC) + - Octave support (except for type itdhorizontal) + - dependency on function 'npi2pi' removed (required toolbox in Matlab; in Octave not supported; outdated anyway) + - keyvalue 'R'/'r' renamed to 'receiver' + - Obj.GLOBAL_Title only displayed in figure title if not empty; title handling improved +- SOFAplotGeometry: + - bug fixed when extracting LU (listener up) coordinates + - minor bugs fixed +- headers of functions checked, updated, author format changed to machine-readable format (#author) +- helper folder renamed to helpers; just SOFAcalculateITD moved to this directory, folder is prepared for downloadable third-party functions +- helper functions removed; some functions are already supported by MATLAB, a few functionalities were implemented in the files themselves +- isoctave.m removed, replaced by code in files + +## TO-DO ## +- SOFAplotGeometry: complete rewrite with extensive support +- SOFAplotGeometry shows a cloud for spatially continuous emitters and receivers + + +************************************************************************************************************ + + +*** v1.1.2 +- SOFAplotGeometry: bug fix if no SourceView given +- FreeFieldDirectivityTF: missing eCM in EmitterPosition fixed +- SOFAcheckFilename: do not convert if filename is http:// +- SOFAplotHRTF: plot TF with regular frequency grid. Not tested for irregular grids, though... + +*** v1.1.1 +- SOFAstart: bug fix when starting for the first time +- SOFAconvertTUBerlinBRIR2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertTHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAconvertFHK2SOFA.m: bug fixed in Obj.ReceiverPosition: left / right was inverted +- SOFAappendText.m: example added to help +- SOFAcompileConventions: fix for changes in Octave 4.2 +- FreeFieldDirectivityTF: updated to version 0.2 + +*** v1.1.0 (not released) +- SOFAremoveVariable added. It removes a variable from the SOFA object. +- SOFAplotGeometry: show SourceView, and bug fix ListenerView. +- SOFAdbPath, SOFAdbURL: reset the path/URL to the default if the parameter is 'reset'. +- SOFAhrtf2dtf: handling for R=1 added. +- SOFAfind added: Find an index for a given position (draft, to be improved). +- SOFAload: provide error message on loading unknown conventions + +*** v1.0.4 (29.4.2019) +- on "SOFA upgrade warning", display a message on how to switch it off +- SOFAplotHRTF: 'magsagittal' added to plot HRTFs along a sagittal plane. +- SOFAload can use filenames beginning with "db://" to indicate to load from the database (local or remote) +- SOFAstart avoids repeated starts now - + - once SOFAstart has been started, SOFAstart won't be executed fully again, when the paths are still available. + - Call SOFAstart('restart') if a restart needs to be forced. + + +*** v1.0.3 (5.9.2018) +- automatic load of the netcdf package in Octave on SOFAstart +- SOFAspat: bugs in normalization, actual position selection removed +- SOFAhrtf2dtf: RMS and weighted averaging added, Octave compatibility ensured +- SOFAcompileConventions: bug fix when compiling conventions in Octave 4.2.1 +- test_SOFAall: suppress irrelevant warnings +- SOFAconvertMIT2SOFA: wavread replaced by audioread +- SOFAconvertConventions: it can convert from SimpleFreeFieldTF to SimpleFreeFieldHRIR. +- SOFAplotHRTF: more variable input of parameters, normalization optional +- SOFAconvertTHK2SOFA: converter from THK format (in miro format) to SOFA added. + +*** v1.0.2 (16.8.2016) +- SOFAplotHRTF: extended to SimpleFreeFieldTF and some cases of GeneralTF +- SOFAplotGeometry: extended to SimpleFreeFieldTF +- SOFAconvertTUBerling2SOFA: uses MultiSpeakerBRIR now +- SOFAspat, SOFAcalculateAPV: minor bug fixes + +*** v1.0.1 (10.6.2015) +- miro class is not supported in Octave. Error is thrown in demo_FHK2SOFA and converterFHK2SOFA +- demo_BTDEI2SOFA: bug fix in renamed BTDEI files +- demo_SOFA2ARI: bug fix in coordinate comparison + +*** v1.0.0 (3.6.2015) +- 'short' flag added to SOFAstart in order to show only a short header on start-up. +- warnings are function-specific now and can be specifically enabled/disabled. + +*** v0.9.1 (13.5.2015) +- 0.9.1 is the internal numbering for the release version 1.0 RC2 +- SimpleFreeFieldSOS added +- SOFAexpand and SOFAaddVariable handle Data. variables now +- SOFAplotHRTF supports SimpleFreeFielsSOS now + +*** v0.9.0 (12.5.2015) + +- 0.9.0 is the internal numbering for the release version 1.0 RC1 +- update of all conventions to SOFA 1.0 +- changes according to the AES212-standard implemented +- Octave: upgraded to a new netcdf-package: http://modb.oce.ulg.ac.be/mediawiki/index.php/Octave-netcdf +- Matlab/Octave: NETCDF* functions merged for both systems (thx to Hagen Wierstorf) +- HRTFs directory: database handling improved: + - SOFAdbPath mirrors http://sofacoustics.org/data now. + - Warning: directory structure of HRTFs/SOFA changed! + - all SOFA files created by demo_ will be saved in sofa_api_mo_test + - all demo_ files which use SOFA files will be automatically downloaded from sofacoustics.org +- clean up of comments +- SOFAcalculateAPV: reimplemented +- horsph and sph2hor: bug fixes +- directory CDL deleted (had historical relevance only) +- SOFAdefinitions: flag 'units' added for unit aliases. +- SOFAgetConventions: returns empty vector if conventions not supported + +*** v0.4.4 (until 20.4.2015) unreleased + +*** v0.4.3 (5.6.2014) by Piotr Majdak +- fix: annoying bug in SOFAupgradeConventions + +*** v0.4.2 (7.4.2014) by Piotr Majdak +- fix: SOFAhrtf2dtf supports more than two receivers + +*** v0.4.1 (30.3.2014) by Piotr Majdak +- MultiSpeakerBRIR conventions added +- SOFAcompact: compacts variables along dimensions, opposite to SOFAexpand. Functionality not complete for 3D variables +- SOFAcompare: compares two SOFA objects. Preliminary functionality; compares attributes only +- SOFAexpand: expanding of Data added +- bug fix: SOFAplotGeometry +- function-specific warnings added: SOFA:upgrade and SOFA:save +- SOFAload optimized for handling huge (3.7 GB) data files on a 4 GB RAM machine + + +*** v0.4 (19.3.2014) by Piotr Majdak +- implements SOFA 0.6: + - GLOBAL_Source renamed to GLOBAL_Origin + - GLOBAL_TimeCreated and GLOBAL_TimeModified renamed to GLOBAL_DateCreated and GLOBAL_DateModified, respectively + - If ListenerUp is provided, ListenerView must be provided as well. If ListenerView is provided, ListenerView_Type and ListenerView_Units must be provided as well. This also applies to Source, Emitter, and Receiver objects. + - Geometry: only "cartesian" or "spherical" coordinate systems allowed + - In SimpleFreeFieldHRIR: GLOBAL_SubjectID renamed to GLOBAL_ListenerShortName +- Converters adapted to provide more precise information +- SOFAappendText added for appending a text to an attribute +- SOFAdefinitions: returns various definitions, depending on the input flag +- SOFAupgradeConventions: upgrades conventions up to 0.6 now. + +*** v0.3.1 (2.9.2013) by Piotr Majdak +- zip file required 7-zip, fixed +- minor bug fixes + +*** v0.3.0 (27.8.2013) by Piotr Majdak +- major change: .API added to the structure, contains .Dimensions and the dimension sizes (formely known as .DimSize) +- implements SOFA 0.5 (without the support for string arrays) +- upgrade of SimpleFreeFieldHRIR 0.3 and other conventions +- syntax of convention files .csv adapted to that from the specs ("_" replaced by ":") +- SOFAcalculateAPV added, provides calculation of the apparent position vector (APV) +- SOFAplotGeometry added, rudimentary plotting available for SimpleFreeFieldHRIR and SingleRoomDRIR +- SOFAaddVariables supports private variables now + +*** v0.2.9 (30.5.2013) by Piotr Majdak +- development snapshot for the draft of SOFA 0.4 +- tested for Matlab (Octave support not finished yet) +- conventions implemented as CSV files which are compiled to MAT at start and are cached by SOFAgetConventions +- user-defined HRTF database path +- seemless download of remote SOFA files on SOFAload +- user-defined HRTF internet repository +- seemless upgrade from SOFA 0.3 files on SOFAload + +*** v0.2.1 (13.5.2013) by Piotr Majdak +- Bug fix with the wrong spelling of "License" +- "License" it very restrictive per default now +- demo_SOFAsave included + +*** v0.2.0 (2.5.2013) by Piotr Majdak +- Updated to SOFA 0.3 +- Octave support added +- demo_* create file names compliant with MS DOS FAT character set +- test script (test/test_SOFAall.m) added +- converters do not add database specific attriubutes, this is done in demo_* +- new demos: SOFAmerge, SOFAload, SOFAsave +- readme improved +- Pulse.sofa removed as binary, it can be created with demo_SOFAsave now +- Link to HRTF files saved as SOFA added (nice for playing around) + +*** v0.1.4 (2.5.2013) by Piotr Majdak +- Major bug fix: dimension order reversed while loading/saving in Matlab +- Some other minor issues closed +- Ready for intercompatibility test between Matlab and Octave + +*** v0.1.3 (18.4.2013) by Piotr Majdak +- This version implements SOFA specs version 0.2 with the following limitations: + - no Octave support + - only SimpleFreeFieldHRIR supported and tested + +- Detailed changes: + - directory structure changed + - new converter added: SOFA2ARI + - SOFAdbPath added + +*** v0.1.2 (17.4.2013) by Piotr Majdak +- SOFAload: partial loading added. Load of metadata only or by measurement section +- docs: changes since AES2013-specs added. +- history file moved to docs +- Repository cleaned from older stuff + +*** v0.1.1 (16.4.2013) by Piotr Majdak +- SOFAload improved: checks added. Still further checks would be nice, but it can be used now. +- SOFAsave improved: saves user-defined variables +- SOFAexpand added: expands the singleton dimensions in the SOFA object +- Convertors for MIT KEMAR, LISTEN, and CIPIC databases added (with corresponding demos) +- HRTF directory created where all HRTFs should be stored. The convertors rely on that. +- SOFAspat improved, now the engine works better + +*** v0.1.0 (11.4.2013) by Piotr Majdak +- Saving/Loading works in Matlab, it is quite rudimentary now: + - Data and Variables saved as Double + - No string in variables supported yet + - One Conventions implemented and tested (SingleFreeFieldHRIR) + - Loading: no checks (todo) + - Saving: removes optional variables (bug) + - No partial loading/saving yet +- Convertion: ARI2SOFA with demo_ARI2SOFA added +- Spatialization: very rudimentary demo added (SOFAspat and demo_SOFAspat), just for fun + +*** v0.0.12 (12.3.2013) by Piotr Majdak +- Conventions: transmitter renamed to emitter + +*** v0.0.11 (7.3.2013) by Piotr Majdak +- Conventions added +- Octave branch deleted +- Examples: ARI2SOFA as a function +- General: adapted to current specs. Don't use yet. + +*** v0.0.10 (5.3.2013) by Piotr Majdak +- ARI2SOFA: changed to a function now, the fields are more clear defined +- SOFAsave: transmitted and receiver separated, dimensions changed +- Specs have drastically changed - beware of using this version at the current development state + +*** v0.0.9 (31.1.2013) by Piotr Majdak +- included octave part from Hagen Wierstorf +- changed the data structure format +- added try-catch to SOFAsave to avoid open file handles + +*** v0.0.8 (24.08.2012) by Wolfgang Hrauda +- changed data structure format +- updates and fixes in several functions and scripts +- added Eigenmike.sofa as a demo file + +*** v0.0.7 (23.08.2012) by Wolfgang Hrauda +- now using structures or cells as input and output values of functions +- added and renamed several functions and scripts +- updates in several functions and scripts + +*** v0.0.6 (14.08.2012) by Wolfgang Hrauda +- added new functions for coordinate type conversion +- functionality of SOFAgetData slightly expanded +- dismissed function SOFAloadVariables (is now an option in SOFAload) +- "ARI_to_SOFA_lab_setup" updated +- minor fixes in several functions + +*** v0.0.5 (08.08.2012) by Wolfgang Hrauda +- implemented additional dimensions for string variables in SOFAsave +- added new function SOFAloadVariables (a variant of SOFAload) +- added new demo script "ARI_to_SOFA_lab_setup" +- fixes in several functions + +*** v0.0.4 (07.08.2012) by Wolfgang Hrauda +- fixed some issues in SOFAsave +- minor changes in SOFAload +- added new functions SOFAgetID, SOFAgetData, SOFAlistVariables + +*** v0.0.3 (03.08.2012) by Wolfgang Hrauda +- split demo script in two API functions and one script that calls them +- change file extension to 'sofa' + +*** v0.0.2 (01.08.2012) by Wolfgang Hrauda +- finished matrix dimension check + +*** v0.0.1 (31.07.2012) by Wolfgang Hrauda +- demo script that loads ARI .mat file, converts it to SOFA format and writes to .nc-file + then reads all data from .nc.file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m new file mode 100644 index 0000000000000000000000000000000000000000..cecca186bd868f8e57cdd7c8755ae5b2dfb374fc --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFdisplay.m @@ -0,0 +1,18 @@ +function [] = NETCDFdisplay(filename) +%NETCDFDISPLAY +% [] = NETCDFdisplay(filename) displays information about specified SOFA file + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% SOFA Toolbox - function netcdf/NETCDFdisplay +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +ncdisp(filename); + +end %of function diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m new file mode 100644 index 0000000000000000000000000000000000000000..0aa1514c1527747558416da60b1bd5b723fec213 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFload.m @@ -0,0 +1,154 @@ +function [Obj,Dims] = NETCDFload(filename,flags,varargin) +%% NETCDFLOAD +% Obj = NETCDFload(filename,'all') reads the SOFA object OBJ with all data from a SOFA file. +% +% Obj = NETCDFload(filename,'nodata') ignores the data, reads variables. +% +% Obj = NETCDFload(filename,[START COUNT],partialDim) reads only COUNT number of data +% in dimension partialDim (given as string) beginning with the index START. If START +% and COUNT are column vectors, then partialDim has to be a string containing the +% dimension for every column entry. +% +% [Obj,Dims] = NETCDFload(...) returns the dimension variables found in +% the file as a string. + +% #Author: Piotr Majdak: String array support. Works for 1D and 2D strings only. (10.08.2014) +% #Author: Michael Mihocic: 'deblank' command added when loading strings to avoid trailing empty spaces in size of array dimension (14.10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +%% SOFA Toolbox - function netcdf/NETCDFload +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob = 'GLOBAL_'; +globid = netcdf.getConstant('GLOBAL'); + +%% --------------------------- N E T C D F load -------------------------- +% Open the NETCDF file +try + var = 'opening file'; + ncid = netcdf.open(filename,'NC_NOWRITE'); % open file + var = 'inquirying data'; + [numdims,numvars,numglob] = netcdf.inq(ncid); % get number of anything + + % ----- GLOBAL ATTRIBUTES -------------------------------------------- + for ii=0:numglob-1 + var = netcdf.inqAttName(ncid,globid,ii); + Obj.([glob var]) = netcdf.getAtt(ncid,globid,var); + end + + % ----- DIMENSIONS --------------------------------------------------- + dimids = netcdf.inqDimIDs(ncid); + dims = cell(numdims,1); % cell array with dimension names + startp = zeros(numdims,1); % vector with start of a dimension + countp = zeros(numdims,1); % vector with the element count in a dimension + for ii=0:numdims-1 + [var,len] = netcdf.inqDim(ncid,dimids(ii+1)); + Obj.API.(var) = len; + dims{ii+1} = var; + startp(ii+1) = 0; + countp(ii+1) = len; + end + Dims = cell2mat(dims)'; + + % Check the requested measurements + if isnumeric(flags) + partialDimRange = flags; + partialDim = varargin{1}; + for ii=1:length(partialDim) + if Obj.API.(partialDim(ii))<(sum(partialDimRange(ii,:))-1) + error('Requested indices exceed measurement count'); + end; + startp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,1)-1; + countp(strfind(Dims,partialDim(ii))) = partialDimRange(ii,2); + end + end + + + % ----- VARIABLES + ATTRIBUTES --------------------------------------- + varids = netcdf.inqVarIDs(ncid); + for ii=0:numvars-1 + [var,~,vardimids,natts] = netcdf.inqVar(ncid,varids(ii+1)); + % Data + if strfind(var,'Data.'), + if ~strcmp(flags,'nodata') + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.Data.(var(6:end))=dim; + if strfind(dim,'S') % strings + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.Data.(var(6:end))=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.Data.(var(6:end))(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.Data.(var(6:end))=deblank(cellstr(reshape(reshape(data,1,[]),size(data,2),[]))); + end + elseif length(dim)>1 + Obj.Data.(var(6:end))=permute(netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)), length(dim):-1:1); + else + Obj.Data.(var(6:end))=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + end + end + % Variables + else + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + dim=fliplr(cell2mat(dims(vardimids+1))'); + Obj.API.Dimensions.(var)=dim; + if strfind(dim,'S') + if length(dim)>2 % 2D string arrays. ToDo: MdD string arrays + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + s=size(data); + Obj.(var)=cell(s(end:-1:2)); + data=reshape(reshape(data,1,[]),[s(2:end) s(1)]); + for jj=1:s(2) + for kk=1:s(3) + Obj.(var)(kk,jj)=cellstr(squeeze(data(jj,kk,:))'); + end + end + else % 1D string array + data=netcdf.getVar(ncid,varids(ii+1),startp(vardimids+1),countp(vardimids+1)); + Obj.(var)=deblank(cellstr(reshape(reshape(data,1,[]),size(data,2),[]))); + end + elseif length(dim)>1 + Obj.(var)=permute(data, length(dim):-1:1); + else + Obj.(var)=data; + end + end + + if natts + for jj=0:natts-1 + att = netcdf.inqAttName(ncid,varids(ii+1),jj); + attval = netcdf.getAtt(ncid,varids(ii+1),att); + if strfind(var,'Data.'), Obj.Data.([var(6:end) '_' att])=attval; else Obj.([var '_' att])=attval; end + end + end + end + +catch ME + if exist('ncid','var'); netcdf.abort(ncid); end; + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message 10 'See also the error stack before']); +end + +netcdf.close(ncid); diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m new file mode 100644 index 0000000000000000000000000000000000000000..7ddc4223ebdb5d2a076e89100c3c365a26f43816 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/netcdf/NETCDFsave.m @@ -0,0 +1,178 @@ +function NETCDFsave(filename,Obj,Compression) +%NETCDFSAVE +% NETCDFsave(filename,Dataset,Compression) saves all data and metadata to a SOFA file. + +% SOFA Toolbox - function netcdf/NETCDFsave +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +% #Author: Piotr Majdak (09.04.2013) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% + +% If we are running octave we have to import the NETCDF namespace, in order to +% run functions like netcdf.getConstant +if exist('OCTAVE_VERSION','builtin') + import_netcdf; +end + +%% Global definitions +glob='GLOBAL_'; +% Dims='IRENMCQ'; % dimensions + +globid=netcdf.getConstant('GLOBAL'); + +try + var='file creation'; + mode = netcdf.getConstant('NETCDF4'); +% mode = netcdf.getConstant('clobber'); +% mode = bitor(mode,netcdf.getConstant('CLASSIC_MODEL')); + ncid = netcdf.create(filename,mode); + +%% Save global attributes + f=fieldnames(Obj); + + for ii=1:length(f) + if ~isempty(strfind(f{ii},glob)) + var=f{ii}; + netcdf.putAtt(ncid,globid,var(strfind(var,glob)+length(glob):end),Obj.(var)); + end + end + +%% Define dimensions + + Dims=cell2mat(fieldnames(rmfield(Obj.API,'Dimensions'))'); + dimid=nan(size(Dims)); + dimsize=nan(size(Dims)); + for ii=1:length(Dims) + var=Dims(ii); + dimid(ii) = netcdf.defDim(ncid,Dims(ii),Obj.API.(var)); + dimsize(ii)=Obj.API.(var); + end + Sdim=strfind(Dims,'S'); % find the index with string dimension + if isempty(Sdim), Sdim=-1, end; % mark as -1 if not existing + +%% Define metadata variables and their attributes +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varId(ii) = netcdf.defVar(ncid,var,netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varId(ii),true,true,Compression); + for jj=1:length(f) + if ~isempty(strfind(f{jj},[var '_'])) + netcdf.putAtt(ncid,varId(ii),f{jj}(strfind(f{jj},[var '_'])+length([var '_']):end),Obj.(f{jj})); + end + end + end + end + +%% Define data variables and their attributes +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if find(ids==Sdim) % array of strings or numerics? + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_CHAR'),fliplr(dimid(ids))); + else + varIdD(ii) = netcdf.defVar(ncid,['Data.' var],netcdf.getConstant('NC_DOUBLE'),fliplr(dimid(ids))); + end + netcdf.defVarDeflate(ncid,varIdD(ii),true,true,Compression); + for jj=1:length(fod) + if ~isempty(strfind(fod{jj},[var '_'])) + netcdf.putAtt(ncid,varIdD(ii),fod{jj}(strfind(fod{jj},[var '_'])+length([var '_']):end),Obj.Data.(fod{jj})); + end + end + end + end + +%% End of definition + netcdf.endDef(ncid); + +%% Save metadata variables +Dimensions=rmfield(Obj.API.Dimensions,'Data'); +fv=fieldnames(Dimensions); + + for ii=1:length(fv) + var=fv{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Dimensions.(var))'))); + if length(ids)>1 + if iscell(Obj.(var)) + c=char(permute(Obj.(var),length(ids):-1:1)); + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % array 'ext' causes warnings in Octave in next row; 'strings' command would work better than 'zeros' but it is not supported in Octave + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),permute(Obj.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.(var)) + c=char(Obj.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varId(ii),[c ext]); + else + netcdf.putVar(ncid,varId(ii),Obj.(var)); + end + end + end + end + +%% Save data variables +fd=fieldnames(Obj.API.Dimensions.Data); +fod=fieldnames(Obj.Data); + + for ii=1:length(fd) + var=fd{ii}; + if isempty(strfind(var,'_')) % skip all attributes + ids=cell2mat(regexp(Dims,cellstr((Obj.API.Dimensions.Data.(var))'))); + if length(ids)>1 + if iscell(Obj.Data.(var)) + c=char(permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % array 'ext' causes warnings in Octave in next row; 'strings' command would work better than 'zeros' but it is not supported in Octave + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),permute(Obj.Data.(var),length(ids):-1:1)); % we need to reverse the dimension order because Matlab netcdf API saves data in the reverse order + end + else + if iscell(Obj.Data.(var)) + c=char(Obj.Data.(var)); % convert to character array + s=size(c); + ext=zeros([s(1:end-1) Obj.API.S-s(end)]); % extend along the S dimension + netcdf.putVar(ncid,varIdD(ii),[c ext]); + else + netcdf.putVar(ncid,varIdD(ii),Obj.Data.(var)); + end + end + end + end + +catch ME +% if ~strcmp(ME.identifier,'MATLAB:imagesci:netcdf:libraryFailure') + netcdf.close(ncid); +% end + for ii=1:length(ME.stack) + disp(ME.stack(ii)); + end + error(['Error processing ' var 10 ... + 'Error message: ' ME.message]); + +end +netcdf.close(ncid); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/readme.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/readme.txt new file mode 100644 index 0000000000000000000000000000000000000000..ef64976aa6f50cc86d9e0705ccb4500a115980bf --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/readme.txt @@ -0,0 +1,18 @@ +This is a readme file for the SOFA Toolbox for Matlab and Octave. + +* Add the "SOFAtoolbox" directory to Matlab search path: Use "Add Folder" (don't use "Add with Subfolders"!) +* Start the Toolbox: execute "SOFAstart" in Matlab or Octave. +* No HRTF files to play around? Follow the advices in the readme.txt files in the HRTFs directories. +* Explore the Toolbox: execute some of the "demo_" files in the directory "demos". +* Learn more about SOFA: read the specs PDF in the directory "doc". +* Report a bug: send a ticket at https://github.com/sofacoustics/SOFAtoolbox/issues. +* Last changes? check the file "history.txt". + +Tested with Matlab R2018b (and higher) and Octave 4.2.1. + +Contact the main developers: Piotr Majdak <piotr.majdak@oeaw.ac.at> and Michael Mihocic <michael.mihocic@oeaw.ac.at> + +Many thanks go to Hagen Wierstorf <hagen.wierstorf@tu-berlin.de> for the Octave support. + +Acoustics Research Insitute (ARI) +Austrian Academy of Sciences (OeAW) diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m new file mode 100644 index 0000000000000000000000000000000000000000..cbe3827e63be72789083c7b0fce091b3a641170e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/SOFAtoolbox/test/test_SOFAall.m @@ -0,0 +1,326 @@ +% SOFA Toolbox - test script +% Test some of the SOFA Toolbox functionality + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: missing demos added, bugs fixed (09-10.2021) +% #Author: Michael Mihocic: header documentation updated (28.10.2021) +% +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or � as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + +clc; close all; % clean-up first +tic; % timer +SOFAstart; +warning('off','SOFA:upgrade'); +warning('off','SOFA:load'); +warning('off','SOFA:save'); + +%% Test converters TO SOFA +disp(' '); +disp('############################################'); +disp('####### TEST CONVERTERS TO SOFA ########'); +disp('############################################'); + +disp(' '); +disp('!!! Make sure that all source files are available in the HRTFs directories. See individual readme.txt files for more information !!!'); +disp(' '); + +%% demo_ARI2SOFA +disp('************** demo_ARI2SOFA **************'); +clear; +% subjectID='NH4'; % default +demo_ARI2SOFA +subjectID='NH2'; +demo_ARI2SOFA +disp('*** Finished: demo_ARI2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_BTDEI2SOFA +disp('************** demo_BTDEI2SOFA **************'); +clear; +demo_BTDEI2SOFA; +disp('*** Finished: demo_BTDEI2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_CIPIC2SOFA +disp('************** demo_CIPIC2SOFA **************'); +clear; +try + demo_CIPIC2SOFA; + disp('*** Finished: demo_CIPIC2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_CIPIC2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\HRTFs\CIPIC\ directory.') +end +disp(' '); + +%% demo_FHK2SOFA +clear; +% if ~exist('OCTAVE_VERSION','builtin') +disp('************** demo_FHK2SOFA **************'); +demo_FHK2SOFA; +disp('*** Finished: demo_FHK2SOFA (Output: SOFA-file(s))'); disp(' '); +% else +% disp('Skipped: demo_CIPIC2SOFA'); disp(' '); +% end + +%% demo_LISTEN2SOFA +disp('************** demo_LISTEN2SOFA **************'); +clear; +subjectID='1002'; +try + demo_LISTEN2SOFA; + disp('*** Finished: demo_LISTEN2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_LISTEN2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\HRTFs\LISTEN\ directory.') +end +disp(' '); + +%% demo_MIT2SOFA +disp('************** demo_MIT2SOFA **************'); +clear; +% pinna='normal'; % default value +demo_MIT2SOFA; +pinna='large'; +demo_MIT2SOFA; +disp('*** Finished: demo_MIT2SOFA (Output: SOFA-file(s))'); disp(' '); + +%% demo_SCUT2SOFA +disp('************** demo_SCUT2SOFA **************'); +clear; +try + demo_SCUT2SOFA; + disp('*** Finished: demo_SCUT2SOFA (Output: SOFA-file(s))'); +catch + warning('demo_SCUT2SOFA cannot finish successfully. Please make sure to save the source files to the \SOFAtoolbox\HRTFs\SCUT\ directory.') +end +disp(' '); + +%% demo_TUBerlin2SOFA +disp('************** demo_TUBerlin2SOFA **************'); +clear; +radius=[0.5 1 2 3]; +demo_TUBerlin2SOFA; +disp('*** Finished: demo_TUBerlin2SOFA (Output: SOFA-file(s))'); disp(' '); + + +%% Test converters FROM SOFA +disp('############################################'); +disp('###### TEST CONVERTERS FROM SOFA #######'); +disp('############################################'); + +%% demo_SOFA2ARI +disp('************** demo_SOFA2ARI **************'); +clear; +demo_SOFA2ARI; +% SOFAplotGeometry(Obj); +disp('*** Finished: demo_SOFA2ARI'); disp(' '); + +%% demo_SOFAHRTF2DTF +disp('************** demo_SOFAHRTF2DTF **************'); +clear; +demo_SOFAHRTF2DTF; +disp('*** Finished: demo_SOFAHRTF2DTF (Output: Figure(s))'); disp(' '); + + +%% Test SOFA functions +disp('############################################'); +disp('###### TEST SOFA FUNCTIONS #######'); +disp('############################################'); + +%% demo_SOFAload +% Test SOFAload +disp('************** demo_SOFAload **************'); +clear; +demo_SOFAload; +disp('*** Finished: demo_SOFAload'); disp(' '); + +%% demo_SOFAmerge +% Test SOFAmerge and create TU-Berlin KEMAR file with multiple radii +disp('************** demo_SOFAmerge **************'); +clear; +demo_SOFAmerge; +disp('*** Finished: demo_SOFAmerge (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_SOFAplotGeometry +disp('************** demo_SOFAplotGeometry **************'); +clear; +demo_SOFAplotGeometry; +disp('*** Finished: demo_SOFAplotGeometry (Output: Figure(s))'); disp(' '); + +%% demo_SOFAplotHRTF +% Test plotting HRTFs +disp('************** demo_SOFAplotHRTF **************'); +demo_SOFAplotHRTF +disp('*** Finished: demo_SOFAplotHRTF (Output: Figure(s))'); disp(' '); + +% %% demo_plot_trumpet_directivity +% % Test plotting HRTFs +% disp('************** demo_plot_trumpet_directivity **************'); +% demo_plot_trumpet_directivity +% disp('*** Finished: demo_plot_trumpet_directivity (Output: Figure(s))'); disp(' '); + +%% demo_SOFAsave +disp('************** SOFAsave **************'); +clear; +demo_SOFAsave; +disp('*** Finished: SOFAsave (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAspat +% Test SOFAspat, but do not play +disp('************** demo_SOFAspat **************'); +clear; +dontplay=1; +demo_SOFAspat; +disp('*** Finished: demo_SOFAspat (Output: Figure(s))'); disp(' '); + +%% demo_SOFAstrings +% Test using string arrays +disp('************** demo_SOFAstrings **************'); +demo_SOFAstrings +disp('*** Finished: demo_SOFAstrings (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAvariables +% Test variables handling +disp('************** demo_SOFAvariables **************'); +demo_SOFAvariables +disp('*** Finished: demo_SOFAvariables (Output: SOFA-file(s))'); disp(' '); + +%% demo_SOFAexpandcompact +% Test SOFAexpand and SOFAcompact +disp('************** demo_SOFAexpandcompact **************'); +clear; +demo_SOFAexpandcompact; +disp('*** Finished: demo_SOFAexpandcompact'); disp(' '); + +%% demo_SOFAcalculateITD +disp('************** demo_SOFAcalculateITD **************'); +clear; +demo_SOFAcalculateITD; +disp('*** Finished: demo_SOFAcalculateITD (Output: Figure(s))'); disp(' '); + +%% demo_SOFAcalculateLFE +disp('************** demo_SOFAcalculateLFE **************'); +clear; +demo_SOFAcalculateLFE; +disp('*** Finished: demo_SOFAcalculateLFE (Output: Figure(s))'); disp(' '); + + +%% Test SOFA conventions +disp('############################################'); +disp('###### TEST SOFA CONVENTIONS #######'); +disp('############################################'); + +%% demo_FreeFieldDirectivityTF +disp('************** demo_FreeFieldDirectivityTF **************'); +clear; +demo_FreeFieldDirectivityTF; +disp('*** Finished: demo_FreeFieldDirectivityTF (Output: Figure(s))'); disp(' '); + +%% demo_FreeFieldHRIR +disp('************** demo_FreeFieldHRIR **************'); +clear +demo_FreeFieldHRIR; +disp('*** Finished: demo_FreeFieldHRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_FreeFieldHRTF +disp('************** demo_FreeFieldHRTF **************'); +clear; +demo_FreeFieldHRTF; +disp('*** Finished: demo_FreeFieldHRTF (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_General +disp('************** demo_General **************'); +clear +demo_General; +disp('*** Finished: General (Output: SOFA-file(s))'); disp(' '); + +%% demo_GeneralFIR +disp('************** demo_GeneralFIR **************'); +clear +demo_GeneralFIR; +disp('*** Finished: demo_GeneralFIR (Output: SOFA-file(s))'); disp(' '); + +%% GeneralFIRE: outdated, use GeneralFIR-E instead + +%% demo_GeneralFIR-E +% replacing GeneralFIR +disp('************** demo_GeneralFIR_E **************'); +clear +demo_GeneralFIR_E; +disp('*** Finished: GeneralFIR_E (Output: SOFA-file(s))'); disp(' '); + +%% GeneralString: used in demo_SOFAstrings + +%% demo_GeneralTF +disp('************** demo_GeneralTF **************'); +clear +demo_GeneralTF; +disp('*** Finished: GeneralTF (Output: SOFA-file(s))'); disp(' '); + +%% demo_GeneralTF-E +disp('************** demo_GeneralTF_E **************'); +clear +demo_GeneralTF_E; +disp('*** Finished: GeneralTF-E (Output: SOFA-file(s))'); disp(' '); + +%% demo_MultiSpeakerBRIR +disp('************** demo_MultiSpeakerBRIR **************'); +clear +demo_MultiSpeakerBRIR; +disp('*** Finished: MultiSpeakerBRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleFreeFieldHRIR2TF +% Test conversions from SimpleFreeFieldHRIR to SimpleFreeFieldHRTF +disp('************** demo_SimpleFreeFieldHRIR2TF **************'); +clear; +demo_SimpleFreeFieldHRIR2TF; +disp('*** Finished: demo_SimpleFreeFieldHRIR2TF (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleFreeFieldHRSOS +disp('************** demo_SimpleFreeFieldHRSOS **************'); +clear +demo_SimpleFreeFieldHRSOS; +disp('*** Finished: SimpleFreeFieldHRSOS (Output: SOFA-file(s))'); disp(' '); + +%% SimpleFreeFieldHRTF +% used in function demo_SimpleFreeFieldHRIR2TF + +%% demo_SimpleFreeFieldSOS +disp('************** SimpleFreeFieldSOS **************'); +clear +demo_SimpleFreeFieldSOS; +disp('*** Finished: SimpleFreeFieldSOS (Output: SOFA-file(s))'); disp(' '); + +%% demo_SimpleHeadphoneIR +% old name: demo_HpIR +disp('************** demo_SimpleHeadphoneIR **************'); +clear; +demo_SimpleHeadphoneIR; +disp('*** Finished: demo_SimpleHeadphoneIR (Output: Figure(s))'); disp(' '); + +%% demo_SingleRoomDRIROlcldenburg +% Test SingleRoomDRIR +disp('************** demo_SingleRoomDRIROldenburg **************'); +clear +demo_SingleRoomDRIROldenburg; +disp('*** Finished: demo_SingleRoomDRIROldenburg (Output: SOFA-file(s), Figure(s))'); disp(' '); + +%% demo_SingleRoomMIMOSRIR +disp('************** demo_SingleRoomMIMOSRIR **************'); +clear +demo_SingleRoomMIMOSRIR; +disp('*** Finished: demo_SingleRoomMIMOSRIR (Output: SOFA-file(s))'); disp(' '); + +%% demo_SingleRoomSRIR +disp('************** SingleRoomSRIR **************'); +clear +demo_SingleRoomSRIR; +disp('*** Finished: SingleRoomSRIR (Output: SOFA-file(s))'); disp(' '); + +%% Epilogue +disp('##############################################'); +disp('#### COMPLETED ALL DEMOS SUCCESSFULLY ####'); +disp('##############################################'); +toc; % timer diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/API_MO 1.0.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/API_MO 1.0.fodt new file mode 100644 index 0000000000000000000000000000000000000000..8501cc62e07c124f2ea3aed23324efd71d20015c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/API_MO 1.0.fodt @@ -0,0 +1,1280 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 1.0</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>247</meta:editing-cycles><meta:editing-duration>P2DT12H58S</meta:editing-duration><meta:generator>LibreOffice/6.2.4.2$Windows_X86_64 LibreOffice_project/2412653d852ce75f65fbfa83fb7e7b669a126d64</meta:generator><dc:date>2019-07-30T11:18:40.946000000</dc:date><dc:creator>Piotr Majdak</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="35" meta:word-count="431" meta:character-count="2885" meta:non-whitespace-character-count="2506"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">28737</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">17969</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">13183</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">1820</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">28736</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">17967</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">13923478</config:config-item> + <config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Mangal1" svg:font-family="Mangal"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial1" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" loext:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Zeichenformat" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial1"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial1"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" loext:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00d41fec" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T19" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T20" style:family="text"> + <style:text-properties officeooo:rsid="00d41fec"/> + </style:style> + <style:style style:name="T21" style:family="text"> + <style:text-properties officeooo:rsid="00d47496"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L3"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">Matlab/Octave API for SOFA </text:span><text:title>version 1.0</text:title><text:tab/><text:span text:style-name="T2"><text:tab/>Page: </text:span><text:span text:style-name="T2"><text:page-number text:select-page="current">1</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P29">Matlab/Octave API for SOFA</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T10">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T6">Acoustics Research Institute </text:span><text:span text:style-name="T9">(ARI)</text:span><text:span text:style-name="T6">, <text:line-break/>Austrian Academy of Sciences </text:span><text:span text:style-name="T9">(OeAW)</text:span><text:span text:style-name="T6"><text:line-break/></text:span><text:span text:style-name="T7">Vienna</text:span><text:span text:style-name="T6">, Austria</text:span><text:span text:style-name="T10"><text:line-break/></text:span><text:span text:style-name="T8"><</text:span><text:span text:style-name="T5">piotr@majdak.com</text:span><text:span text:style-name="T8">></text:span></text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T16">This document contains preliminary remarks on the <text:line-break/>API_MO </text:span><text:span text:style-name="T16"><text:title>version 1.0</text:title></text:span><text:span text:style-name="T16">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T17">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list2795606257" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P30"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P40"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T10">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P30"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T15">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T15">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P31"><text:span text:style-name="Strong_20_Emphasis">Wolfgang Hrauda </text:span><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T5">wolfgang.hrauda@gmx.at</text:span></text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P32" text:outline-level="2"/> + <text:h text:style-name="P7" text:outline-level="1">STARTING the API</text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T19">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the API.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt <text:span text:style-name="T20">or help SOFAstart.</text:span></text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the API are provided. This is the first place to get familiar with the structure of the API.</text:p> + <text:p text:style-name="P23">Note that for the demonstration of conversion functions, you will most probably need to download some non-SOFA HRTF files first. See readme.txt files in the HRTF directories of the corresponding non-SOFA format.</text:p> + <text:h text:style-name="P6" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P16">All the SOFA information is stored in the a variable which we call SOFA object here. <text:span text:style-name="T20">Such an object is, for example, returned by the function SOFAload. </text:span>In that object:</text:p> + <text:list xml:id="list1306107549" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P33">“GLOBAL_” <text:span text:style-name="T20">are all g</text:span>lobal attributes. <text:span text:style-name="T21">Use prefix GLOBAL_ to add your global attributes.</text:span> </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P36">Variables are stored with their names as they are.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="T20">An a</text:span>ttribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P34">“Data.” <text:span text:style-name="T20">is a </text:span>separate structure <text:span text:style-name="T20">containing </text:span>the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33">“PRIVATE” <text:span text:style-name="T20">is a</text:span> structure with private data for application use. <text:span text:style-name="T20">Here you can store your private variables which belong to the SOFA object. P</text:span>rivate <text:span text:style-name="T20">variables</text:span> won't be saved when saving <text:span text:style-name="T20">the</text:span> object <text:span text:style-name="T20">as a SOFA file.</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35">“API” <text:span text:style-name="T20">contains </text:span>internal variables <text:span text:style-name="T20">of the API. Do not modify them, use SOFAupdateDimensions() to update them according to your data. These variables</text:span> are <text:span text:style-name="T21">useful for handling the SOFA data</text:span>:</text:p> + <text:list> + <text:list-item> + <text:p text:style-name="P35">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">Use SOFAaddVariable() to add a new variable. </text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P17">Further resources can be found:</text:p> + <text:list xml:id="list2018448349" text:style-name="L3"> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T20">API_MO</text:span>/readme.txt provides a short description of the API.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T20">API_MO</text:span>/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">doc/specs provides specifications of the currently supported SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/SOFA stores SOFA files. Per default, it mirrors http://sofacoustics.org/data.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/SOFA/sofa_api_mo_test: here, the automatically created SOFA files will be saved for testing purposes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">HRTFs/other directories: directories containing HRTF files stored in other formats than SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">http://sofaconventions.org provides the most recent information on SOFA.</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt new file mode 100644 index 0000000000000000000000000000000000000000..63ebe4d9a21843cd82c9280b34b99372606617a0 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/API_MO specs 0.4.fodt @@ -0,0 +1,1248 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rpt="http://openoffice.org/2005/report" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:officeooo="http://openoffice.org/2009/office" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 0.4</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>234</meta:editing-cycles><meta:editing-duration>P2DT11H41M48S</meta:editing-duration><meta:generator>LibreOffice/4.2.1.1$Windows_x86 LibreOffice_project/d7dbbd7842e6a58b0f521599204e827654e1fb8b</meta:generator><dc:date>2014-03-20T17:53:51.716000000</dc:date><dc:creator>Piotr Majdak</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="28" meta:word-count="272" meta:character-count="1831" meta:non-whitespace-character-count="1599"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="int">34555</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="int">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="int">26169</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="int">21063</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="int">15688</config:config-item> + <config:config-item config:name="ViewTop" config:type="int">37447</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="int">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="int">34555</config:config-item> + <config:config-item config:name="VisibleRight" config:type="int">26167</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="int">55615</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">13612822</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Mangal1" svg:font-family="Mangal"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal1" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L3"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L4"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:list-style-name="L1"/> + <style:style style:name="P26" style:family="paragraph" style:list-style-name="L2"/> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L3"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L4"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:layout-grid-snap-to-characters="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:layout-grid-snap-to-characters="true" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:footnote-max-height="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">Matlab and Octave API for SOFA </text:span><text:title>version 0.4</text:title><text:tab/><text:span text:style-name="T2"><text:tab/>Page: </text:span><text:span text:style-name="T2"><text:page-number text:select-page="current">2</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P29">Matlab and Octave API for SOFA</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T9">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T6">Acoustics Research Institute, Austrian Academy of Sciences, </text:span><text:span text:style-name="T7">Vienna</text:span><text:span text:style-name="T6">, Austria</text:span><text:span text:style-name="T9"><text:line-break/></text:span><text:span text:style-name="T8"><</text:span><text:span text:style-name="T5">piotr@majdak.com</text:span><text:span text:style-name="T8">></text:span></text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T15">This document contains preliminary remarks on the <text:line-break/>API_MO </text:span><text:span text:style-name="T15"><text:title>version 0.4</text:title></text:span><text:span text:style-name="T15">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T16">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list6831239085214927904" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P17"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P24"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T9">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P17"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T14">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T14">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P18" text:outline-level="2"/> + <text:h text:style-name="P28" text:outline-level="1">STARTING the API</text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T18">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the API.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt.</text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the API are provided. This is the first place to get familiar with the structure of the API.</text:p> + <text:h text:style-name="P27" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P23">All the SOFA information is stored in the a variable which we call SOFA object here. In that object:</text:p> + <text:list xml:id="list382891697804604485" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P19">“Data.”: separate structure with the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">“GLOBAL_”: Global attributes </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">Attribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">“PRIVATE”: structure with private data for application use. Private data won't be saved when saving a SOFA object. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P19">API internal variables are:</text:p> + </text:list-item> + </text:list> + <text:list xml:id="list7731056547229950280" text:style-name="L4"> + <text:list-item> + <text:p text:style-name="P22">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P22">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P20">Further resources can be found:</text:p> + <text:list xml:id="list1373325075875023343" text:style-name="L3"> + <text:list-item> + <text:p text:style-name="P21">api_mo/readme.txt provides a short description of the API.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">api_mo/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">doc/specs provides specifications of the currently supported SOFA</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P21">http://sofaconventions.org provides the most recent information on SOFA</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/Conventions2Wiki.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/Conventions2Wiki.m new file mode 100644 index 0000000000000000000000000000000000000000..36d1c1bed5a615c7c4e83b2cdb8387705d34dced --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/Conventions2Wiki.m @@ -0,0 +1,36 @@ +%% Convert all convention files to Wiki tables + +% #Author: Piotr Majdak +% #Author: Michael Mihocic: header documentation updated, license text added (28.10.2021) + +% SOFA Toolbox +% Copyright (C) Acoustics Research Institute - Austrian Academy of Sciences +% Licensed under the EUPL, Version 1.2 or - as soon they will be approved by the European Commission - subsequent versions of the EUPL (the "License") +% You may not use this work except in compliance with the License. +% You may obtain a copy of the License at: https://joinup.ec.europa.eu/software/page/eupl +% Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +% See the License for the specific language governing permissions and limitations under the License. + + +p=fullfile('..','SOFAtoolbox','conventions'); +d=dir([p filesep '*.csv']); +conventions={}; +for ii=1:length(d) + dn=d(ii).name; + conventions{ii}=dn(1:end-4); +end + +for jj=1:length(conventions) + fid=fopen([p filesep conventions{jj} '.csv']); + C=textscan(fid,'%s%s%s%s%s%s','Delimiter','\t','Headerlines',1); + fclose(fid); + fid=fopen([conventions{jj} '.txt'],'w'); + fprintf(fid,'{| border="1"\n!Name\n!Default\n![[SOFA_conventions#AnchorFlags|Flags]]\n![[SOFA_conventions#AnchorDimensions|Dimensions]]\n!Type\n!Comment\n'); +% C2=regexprep(C{2},'''', '’'); % replace single quota (') by ′ + for ii=1:length(C{1}) + fprintf(fid,['|-\n|' C{1}{ii} '||<nowiki>' C{2}{ii} '</nowiki>||' C{3}{ii} '||' C{4}{ii} '||' C{5}{ii} '||' C{6}{ii} '\n']); + end + fprintf(fid,'|}'); + fclose(fid); +end +disp (' ** done **'); \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/Toolbox 2.0.fodt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/Toolbox 2.0.fodt new file mode 100644 index 0000000000000000000000000000000000000000..4afadfdb8e9f077972c747328dad97521cb85dd1 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/doc/Toolbox 2.0.fodt @@ -0,0 +1,1277 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<office:document xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" xmlns:rpt="http://openoffice.org/2005/report" xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" xmlns:ooow="http://openoffice.org/2004/writer" xmlns:oooc="http://openoffice.org/2004/calc" xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" xmlns:tableooo="http://openoffice.org/2009/table" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:drawooo="http://openoffice.org/2010/draw" xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0" xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" xmlns:math="http://www.w3.org/1998/Math/MathML" xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" xmlns:dom="http://www.w3.org/2001/xml-events" xmlns:xforms="http://www.w3.org/2002/xforms" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:grddl="http://www.w3.org/2003/g/data-view#" xmlns:css3t="http://www.w3.org/TR/css3-text/" xmlns:officeooo="http://openoffice.org/2009/office" office:version="1.3" office:mimetype="application/vnd.oasis.opendocument.text"> + <office:meta><dc:title>version 2.0</dc:title><meta:initial-creator>Piotr Majdak</meta:initial-creator><meta:creation-date>2013-04-18T09:55:47.880000000</meta:creation-date><meta:editing-cycles>250</meta:editing-cycles><meta:editing-duration>P2DT12H5M37S</meta:editing-duration><meta:generator>LibreOffice/7.3.4.2$Windows_X86_64 LibreOffice_project/728fec16bd5f605073805c3c9e7c4212a0120dc5</meta:generator><dc:date>2022-07-28T13:12:29.231000000</dc:date><dc:creator>Michael Mihocic</dc:creator><meta:document-statistic meta:table-count="0" meta:image-count="0" meta:object-count="0" meta:page-count="2" meta:paragraph-count="36" meta:word-count="436" meta:character-count="2961" meta:non-whitespace-character-count="2578"/><meta:user-defined meta:name="Mendeley Citation Style_1">http://www.zotero.org/styles/ieee-audio-speech-and-language-processing</meta:user-defined><meta:user-defined meta:name="Mendeley Document_1">True</meta:user-defined><meta:user-defined meta:name="Mendeley User Name_1">piotr@majdak.com@www.mendeley.com</meta:user-defined></office:meta> + <office:settings> + <config:config-item-set config:name="ooo:view-settings"> + <config:config-item config:name="ViewAreaTop" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaLeft" config:type="long">0</config:config-item> + <config:config-item config:name="ViewAreaWidth" config:type="long">38022</config:config-item> + <config:config-item config:name="ViewAreaHeight" config:type="long">18840</config:config-item> + <config:config-item config:name="ShowRedlineChanges" config:type="boolean">true</config:config-item> + <config:config-item config:name="InBrowseMode" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="Views"> + <config:config-item-map-entry> + <config:config-item config:name="ViewId" config:type="string">view2</config:config-item> + <config:config-item config:name="ViewLeft" config:type="long">21701</config:config-item> + <config:config-item config:name="ViewTop" config:type="long">9500</config:config-item> + <config:config-item config:name="VisibleLeft" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleTop" config:type="long">0</config:config-item> + <config:config-item config:name="VisibleRight" config:type="long">38021</config:config-item> + <config:config-item config:name="VisibleBottom" config:type="long">18838</config:config-item> + <config:config-item config:name="ZoomType" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutColumns" config:type="short">0</config:config-item> + <config:config-item config:name="ViewLayoutBookMode" config:type="boolean">false</config:config-item> + <config:config-item config:name="ZoomFactor" config:type="short">100</config:config-item> + <config:config-item config:name="IsSelectedFrame" config:type="boolean">false</config:config-item> + <config:config-item config:name="KeepRatio" config:type="boolean">false</config:config-item> + <config:config-item config:name="AnchoredTextOverflowLegacy" config:type="boolean">false</config:config-item> + </config:config-item-map-entry> + </config:config-item-map-indexed> + </config:config-item-set> + <config:config-item-set config:name="ooo:configuration-settings"> + <config:config-item config:name="ProtectForm" config:type="boolean">false</config:config-item> + <config:config-item-map-indexed config:name="ForbiddenCharacters"> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">DE</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">en</config:config-item> + <config:config-item config:name="Country" config:type="string">US</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">ja</config:config-item> + <config:config-item config:name="Country" config:type="string">JP</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string">!%),.:;?]}¢°’”‰′″℃、。々〉》」』】〕゛゜ゝゞ・ヽヾ!%),.:;?]}。」、・゙゚¢</config:config-item> + <config:config-item config:name="EndLine" config:type="string">$([\{£¥‘“〈《「『【〔$([{「£¥</config:config-item> + </config:config-item-map-entry> + <config:config-item-map-entry> + <config:config-item config:name="Language" config:type="string">de</config:config-item> + <config:config-item config:name="Country" config:type="string">AT</config:config-item> + <config:config-item config:name="Variant" config:type="string"/> + <config:config-item config:name="BeginLine" config:type="string"/> + <config:config-item config:name="EndLine" config:type="string"/> + </config:config-item-map-entry> + </config:config-item-map-indexed> + <config:config-item config:name="PrinterName" config:type="string"/> + <config:config-item config:name="EmbeddedDatabaseName" config:type="string"/> + <config:config-item config:name="CurrentDatabaseDataSource" config:type="string"/> + <config:config-item config:name="LinkUpdateMode" config:type="short">1</config:config-item> + <config:config-item config:name="AddParaTableSpacingAtStart" config:type="boolean">true</config:config-item> + <config:config-item config:name="FloattableNomargins" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnbreakableNumberings" config:type="boolean">true</config:config-item> + <config:config-item config:name="FieldAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddVerticalFrameOffsets" config:type="boolean">false</config:config-item> + <config:config-item config:name="BackgroundParaOverDrawings" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaTableSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="ChartAutoUpdate" config:type="boolean">true</config:config-item> + <config:config-item config:name="CurrentDatabaseCommand" config:type="string"/> + <config:config-item config:name="PrinterSetup" config:type="base64Binary"/> + <config:config-item config:name="AlignTabStopPosition" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrinterPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="IsKernAsianPunctuation" config:type="boolean">false</config:config-item> + <config:config-item config:name="CharacterCompressionType" config:type="short">0</config:config-item> + <config:config-item config:name="ApplyUserData" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotJustifyLinesWithManualBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SaveThumbnail" config:type="boolean">true</config:config-item> + <config:config-item config:name="SaveGlobalDocumentLinks" config:type="boolean">false</config:config-item> + <config:config-item config:name="SmallCapsPercentage66" config:type="boolean">false</config:config-item> + <config:config-item config:name="CurrentDatabaseCommandType" config:type="int">0</config:config-item> + <config:config-item config:name="SaveVersionOnClose" config:type="boolean">false</config:config-item> + <config:config-item config:name="UpdateFromTemplate" config:type="boolean">true</config:config-item> + <config:config-item config:name="DoNotCaptureDrawObjsOnPage" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerObjectPositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintSingleJobs" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedSystemFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrinterIndependentLayout" config:type="string">high-resolution</config:config-item> + <config:config-item config:name="IsLabelDocument" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddFrameOffsets" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddExternalLeading" config:type="boolean">true</config:config-item> + <config:config-item config:name="MsWordCompMinLineHeightByFly" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="OutlineLevelYieldsNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="DoNotResetParaAttrsForNumFont" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreFirstLineIndentInNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="AllowPrintJobCancel" config:type="boolean">true</config:config-item> + <config:config-item config:name="UseFormerLineSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="AddParaSpacingToTableCells" config:type="boolean">true</config:config-item> + <config:config-item config:name="AddParaLineSpacingToTableCells" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseFormerTextWrapping" config:type="boolean">false</config:config-item> + <config:config-item config:name="RedlineProtectionKey" config:type="base64Binary"/> + <config:config-item config:name="ConsiderTextWrapOnObjPos" config:type="boolean">true</config:config-item> + <config:config-item config:name="TableRowKeep" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabsRelativeToIndent" config:type="boolean">false</config:config-item> + <config:config-item config:name="IgnoreTabsAndBlanksForLineCalculation" config:type="boolean">true</config:config-item> + <config:config-item config:name="RsidRoot" config:type="int">916693</config:config-item> + <config:config-item config:name="LoadReadonly" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClipAsCharacterAnchoredWriterFlyFrames" config:type="boolean">false</config:config-item> + <config:config-item config:name="UnxForceZeroExtLeading" config:type="boolean">false</config:config-item> + <config:config-item config:name="UseOldPrinterMetrics" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabAtLeftIndentForParagraphsInList" config:type="boolean">false</config:config-item> + <config:config-item config:name="Rsid" config:type="int">14009041</config:config-item> + <config:config-item config:name="MsWordCompTrailingBlanks" config:type="boolean">false</config:config-item> + <config:config-item config:name="MathBaselineAlignment" config:type="boolean">true</config:config-item> + <config:config-item config:name="InvertBorderSpacing" config:type="boolean">true</config:config-item> + <config:config-item config:name="CollapseEmptyCellPara" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverflow" config:type="boolean">true</config:config-item> + <config:config-item config:name="StylesNoDefault" config:type="boolean">false</config:config-item> + <config:config-item config:name="ClippedPictures" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedOnlyUsedFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedLatinScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmbedAsianScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="EmptyDbFieldHidesPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="EmbedComplexScriptFonts" config:type="boolean">true</config:config-item> + <config:config-item config:name="TabOverMargin" config:type="boolean">false</config:config-item> + <config:config-item config:name="TabOverSpacing" config:type="boolean">false</config:config-item> + <config:config-item config:name="TreatSingleColumnBreakAsPageBreak" config:type="boolean">false</config:config-item> + <config:config-item config:name="SurroundTextWrapSmall" config:type="boolean">false</config:config-item> + <config:config-item config:name="ApplyParagraphMarkFormatToNumbering" config:type="boolean">false</config:config-item> + <config:config-item config:name="PropLineSpacingShrinksFirstLine" config:type="boolean">false</config:config-item> + <config:config-item config:name="SubtractFlysAnchoredAtFlys" config:type="boolean">true</config:config-item> + <config:config-item config:name="DisableOffPagePositioning" config:type="boolean">false</config:config-item> + <config:config-item config:name="ContinuousEndnotes" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectBookmarks" config:type="boolean">false</config:config-item> + <config:config-item config:name="ProtectFields" config:type="boolean">false</config:config-item> + <config:config-item config:name="HeaderSpacingBelowLastPara" config:type="boolean">false</config:config-item> + <config:config-item config:name="FrameAutowidthWithMorePara" config:type="boolean">false</config:config-item> + <config:config-item config:name="GutterAtTop" config:type="boolean">false</config:config-item> + <config:config-item config:name="FootnoteInColumnToPageEnd" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintAnnotationMode" config:type="short">0</config:config-item> + <config:config-item config:name="PrintGraphics" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintBlackFonts" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintLeftPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintControls" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintPageBackground" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintTextPlaceholder" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintDrawings" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintHiddenText" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintProspect" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintTables" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintProspectRTL" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintReversed" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintRightPages" config:type="boolean">true</config:config-item> + <config:config-item config:name="PrintFaxName" config:type="string"/> + <config:config-item config:name="PrintPaperFromSetup" config:type="boolean">false</config:config-item> + <config:config-item config:name="PrintEmptyPages" config:type="boolean">false</config:config-item> + </config:config-item-set> + </office:settings> + <office:scripts> + <office:script script:language="ooo:Basic"> + <ooo:libraries xmlns:ooo="http://openoffice.org/2004/office" xmlns:xlink="http://www.w3.org/1999/xlink"> + <ooo:library-embedded ooo:name="Standard"/> + </ooo:libraries> + </office:script> + </office:scripts> + <office:font-face-decls> + <style:font-face style:name="Arial" svg:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Arial1" svg:font-family="Arial" style:font-adornments="Regular" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Courier New" svg:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="Garamond" svg:font-family="Garamond" style:font-adornments="Regular" style:font-family-generic="roman" style:font-pitch="variable"/> + <style:font-face style:name="Helvetica" svg:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable"/> + <style:font-face style:name="Mangal" svg:font-family="Mangal"/> + <style:font-face style:name="Mangal1" svg:font-family="Mangal" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="NSimSun" svg:font-family="NSimSun" style:font-family-generic="modern" style:font-pitch="fixed"/> + <style:font-face style:name="OpenSymbol" svg:font-family="OpenSymbol"/> + <style:font-face style:name="SimSun" svg:font-family="SimSun" style:font-family-generic="system" style:font-pitch="variable"/> + <style:font-face style:name="Times New Roman" svg:font-family="'Times New Roman'" style:font-family-generic="roman" style:font-pitch="variable"/> + </office:font-face-decls> + <office:styles> + <style:default-style style:family="graphic"> + <style:graphic-properties svg:stroke-color="#808080" draw:fill-color="#cfe7f5" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" draw:start-line-spacing-vertical="0.283cm" draw:end-line-spacing-horizontal="0.283cm" draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/> + <style:paragraph-properties style:text-autospace="ideograph-alpha" style:line-break="strict" style:writing-mode="lr-tb" style:font-independent-line-spacing="false"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN"/> + </style:default-style> + <style:default-style style:family="paragraph"> + <style:paragraph-properties fo:hyphenation-ladder-count="no-limit" style:text-autospace="ideograph-alpha" style:punctuation-wrap="hanging" style:line-break="strict" style:tab-stop-distance="1.27cm" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Times New Roman" fo:font-size="12pt" fo:language="en" fo:country="US" style:letter-kerning="true" style:font-name-asian="SimSun" style:font-size-asian="10.5pt" style:language-asian="zh" style:country-asian="CN" style:font-name-complex="Mangal1" style:font-size-complex="12pt" style:language-complex="hi" style:country-complex="IN" fo:hyphenate="false" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:default-style> + <style:default-style style:family="table"> + <style:table-properties table:border-model="collapsing"/> + </style:default-style> + <style:default-style style:family="table-row"> + <style:table-row-properties fo:keep-together="auto"/> + </style:default-style> + <style:style style:name="Standard" style:family="paragraph" style:class="text"> + <style:paragraph-properties fo:orphans="2" fo:widows="2" style:writing-mode="lr-tb"/> + <style:text-properties style:use-window-font-color="true" loext:opacity="0%" style:font-name="Garamond" fo:font-family="Garamond" style:font-style-name="Regular" style:font-family-generic="roman" style:font-pitch="variable" fo:font-size="10pt" fo:language="en" fo:country="US" style:font-name-asian="Times New Roman" style:font-family-asian="'Times New Roman'" style:font-family-generic-asian="roman" style:font-pitch-asian="variable" style:font-size-asian="10pt" style:font-name-complex="Times New Roman" style:font-family-complex="'Times New Roman'" style:font-family-generic-complex="roman" style:font-pitch-complex="variable" style:font-size-complex="12pt" style:language-complex="ar" style:country-complex="SA"/> + </style:style> + <style:style style:name="Heading" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.106cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="16pt" fo:font-weight="bold" style:letter-kerning="true" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Text_20_body" style:display-name="Text body" style:family="paragraph" style:parent-style-name="Standard" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-top="0.212cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="justify" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" fo:text-indent="0cm" style:auto-text-indent="false" style:page-number="auto" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"/> + <style:text-properties style:font-size-complex="10pt" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:style> + <style:style style:name="List" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="list"> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Caption" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-top="0.212cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Index" style:family="paragraph" style:parent-style-name="Standard" style:class="index"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + <style:text-properties style:font-size-asian="12pt" style:font-name-complex="Mangal" style:font-family-complex="Mangal"/> + </style:style> + <style:style style:name="Heading_20_1" style:display-name="Heading 1" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="1" style:class="text" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.635cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" style:page-number="auto" fo:break-before="auto" fo:break-after="auto" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:text-transform="uppercase" style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable"/> + </style:style> + <style:style style:name="Heading_20_2" style:display-name="Heading 2" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="2" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial" fo:font-family="Arial" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Arial" style:font-family-complex="Arial" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_3" style:display-name="Heading 3" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:default-outline-level="3" style:class="text"> + <style:paragraph-properties fo:margin-left="0.953cm" fo:margin-right="0cm" fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-indent="-0.953cm" style:auto-text-indent="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties style:font-name="Helvetica" fo:font-family="Helvetica" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-weight="bold" style:font-weight-asian="bold" style:font-name-complex="Helvetica" style:font-family-complex="Helvetica" style:font-family-generic-complex="swiss" style:font-pitch-complex="variable" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Heading_20_4" style:display-name="Heading 4" style:family="paragraph" style:parent-style-name="Standard" style:next-style-name="Text_20_body" style:class="text"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:line-height="150%" fo:text-align="justify" style:justify-single-word="false" fo:keep-with-next="always" style:text-autospace="none" style:punctuation-wrap="simple" style:vertical-align="baseline"> + <style:tab-stops> + <style:tab-stop style:position="1.397cm"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Figure_20_Caption" style:display-name="Figure Caption" style:family="paragraph" style:parent-style-name="Text_20_body" style:next-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="Reference" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="" style:master-page-name=""> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:orphans="0" fo:widows="0" fo:text-indent="-0.499cm" style:auto-text-indent="false" style:page-number="auto"> + <style:tab-stops/> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header_20_and_20_Footer" style:display-name="Header and Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"> + <style:tab-stops> + <style:tab-stop style:position="8.5cm" style:type="center"/> + <style:tab-stop style:position="17cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Header" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" style:page-number="auto" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Footer" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" style:page-number="auto" fo:padding="0cm" fo:border="none" style:shadow="none"> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.24cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties style:font-name="Arial1" fo:font-family="Arial" style:font-style-name="Regular" style:font-family-generic="swiss" style:font-pitch="variable" fo:font-size="11pt"/> + </style:style> + <style:style style:name="Frame_20_contents" style:display-name="Frame contents" style:family="paragraph" style:parent-style-name="Text_20_body" style:class="extra"/> + <style:style style:name="Table_20_Contents" style:display-name="Table Contents" style:family="paragraph" style:parent-style-name="Standard" style:class="extra" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="8pt"/> + </style:style> + <style:style style:name="Table_20_Heading" style:display-name="Table Heading" style:family="paragraph" style:parent-style-name="Table_20_Contents" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Figure" style:family="paragraph" style:parent-style-name="Caption" style:class="extra" style:master-page-name=""> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false" fo:hyphenation-ladder-count="no-limit" style:page-number="auto"/> + <style:text-properties fo:font-weight="normal" fo:hyphenate="true" fo:hyphenation-remain-char-count="2" fo:hyphenation-push-char-count="2" loext:hyphenation-no-caps="false"/> + </style:style> + <style:style style:name="Table" style:family="paragraph" style:parent-style-name="Caption" style:class="extra"> + <style:paragraph-properties fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-weight="normal"/> + </style:style> + <style:style style:name="Heading_20_5" style:display-name="Heading 5" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:default-outline-level="5" style:class="text"> + <style:text-properties fo:font-size="85%" fo:font-weight="bold" style:font-size-asian="85%" style:font-weight-asian="bold" style:font-size-complex="85%" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote" style:family="paragraph" style:parent-style-name="Standard" style:class="extra"> + <style:paragraph-properties fo:margin-left="0.3cm" fo:margin-right="0cm" fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-indent="-0.3cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"> + <style:tab-stops/> + </style:paragraph-properties> + <style:text-properties fo:font-size="8pt" style:font-size-asian="10pt" style:font-size-complex="10pt"/> + </style:style> + <style:style style:name="Title" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Subtitle" style:class="chapter" style:master-page-name=""> + <style:paragraph-properties fo:margin-top="3cm" fo:margin-bottom="3cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false" style:page-number="auto"/> + <style:text-properties fo:font-size="18pt" fo:font-weight="bold" style:font-size-asian="18pt" style:font-weight-asian="bold" style:font-size-complex="18pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Subtitle" style:family="paragraph" style:parent-style-name="Heading" style:next-style-name="Text_20_body" style:class="chapter"> + <style:paragraph-properties fo:margin-top="0.42cm" fo:margin-bottom="2cm" style:contextual-spacing="false" fo:text-align="center" style:justify-single-word="false"/> + <style:text-properties fo:font-size="12pt" fo:font-style="normal" style:font-size-asian="14pt" style:font-style-asian="italic" style:font-size-complex="14pt" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Signature" style:family="paragraph" style:parent-style-name="Standard" style:class="text"> + <style:paragraph-properties text:number-lines="false" text:line-number="0"/> + </style:style> + <style:style style:name="Index_20_Heading" style:display-name="Index Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_Heading" style:display-name="Contents Heading" style:family="paragraph" style:parent-style-name="Heading" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false" text:number-lines="false" text:line-number="0"/> + <style:text-properties fo:font-size="16pt" fo:font-weight="bold" style:font-size-asian="16pt" style:font-weight-asian="bold" style:font-size-complex="16pt" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Contents_20_1" style:display-name="Contents 1" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="14.002cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_2" style:display-name="Contents 2" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.499cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.503cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Contents_20_3" style:display-name="Contents 3" style:family="paragraph" style:parent-style-name="Index" style:class="index"> + <style:paragraph-properties fo:margin-left="0.998cm" fo:margin-right="0cm" fo:text-indent="0cm" style:auto-text-indent="false"> + <style:tab-stops> + <style:tab-stop style:position="13.003cm" style:type="right" style:leader-style="dotted" style:leader-text="."/> + </style:tab-stops> + </style:paragraph-properties> + </style:style> + <style:style style:name="Numbering_20_Symbols" style:display-name="Numbering Symbols" style:family="text"/> + <style:style style:name="Emphasis" style:family="text"> + <style:text-properties fo:font-style="italic" style:font-style-asian="italic" style:font-style-complex="italic"/> + </style:style> + <style:style style:name="Bullet_20_Symbols" style:display-name="Bullet Symbols" style:family="text"> + <style:text-properties style:font-name="OpenSymbol" fo:font-family="OpenSymbol" style:font-name-asian="OpenSymbol" style:font-family-asian="OpenSymbol" style:font-name-complex="OpenSymbol" style:font-family-complex="OpenSymbol"/> + </style:style> + <style:style style:name="Source_20_Text" style:display-name="Source Text" style:family="text"> + <style:text-properties style:font-name="Courier New" fo:font-family="'Courier New'" style:font-family-generic="modern" style:font-pitch="fixed" style:font-name-asian="NSimSun" style:font-family-asian="NSimSun" style:font-family-generic-asian="modern" style:font-pitch-asian="fixed" style:font-name-complex="Courier New" style:font-family-complex="'Courier New'" style:font-family-generic-complex="modern" style:font-pitch-complex="fixed"/> + </style:style> + <style:style style:name="Strong_20_Emphasis" style:display-name="Strong Emphasis" style:family="text"> + <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> + </style:style> + <style:style style:name="Footnote_20_Symbol" style:display-name="Footnote Symbol" style:family="text"/> + <style:style style:name="Footnote_20_anchor" style:display-name="Footnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Endnote_20_Symbol" style:display-name="Endnote Symbol" style:family="text"/> + <style:style style:name="Endnote_20_anchor" style:display-name="Endnote anchor" style:family="text"> + <style:text-properties style:text-position="super 58%"/> + </style:style> + <style:style style:name="Not_20_implemented_20_yet" style:display-name="Not implemented yet" style:family="text"> + <style:text-properties style:text-line-through-style="solid" style:text-line-through-type="single" style:font-size-asian="10.5pt"/> + </style:style> + <style:style style:name="Internet_20_link" style:display-name="Internet link" style:family="text"> + <style:text-properties fo:color="#000080" loext:opacity="100%" fo:language="zxx" fo:country="none" style:text-underline-style="solid" style:text-underline-width="auto" style:text-underline-color="font-color" style:language-asian="zxx" style:country-asian="none" style:language-complex="zxx" style:country-complex="none"/> + </style:style> + <style:style style:name="Index_20_Link" style:display-name="Index Link" style:family="text"/> + <style:style style:name="Zeichenformat" style:family="text"/> + <style:style style:name="Frame" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="parallel" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph-content" style:horizontal-pos="center" style:horizontal-rel="paragraph-content"/> + </style:style> + <style:style style:name="Graphics" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <style:style style:name="OLE" style:family="graphic"> + <style:graphic-properties text:anchor-type="paragraph" svg:x="0cm" svg:y="0cm" style:wrap="dynamic" style:number-wrapped-paragraphs="no-limit" style:wrap-contour="false" style:vertical-pos="top" style:vertical-rel="paragraph" style:horizontal-pos="center" style:horizontal-rel="paragraph"/> + </style:style> + <text:outline-style style:name="Outline"> + <text:outline-level-style text:level="1" loext:num-list-format="%1%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="2" loext:num-list-format="%1%.%2%." style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="3" loext:num-list-format="%1%.%2%.%3%." style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="4" loext:num-list-format="%1%.%2%.%3%.%4%." style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="5" loext:num-list-format="%1%.%2%.%3%.%4%.%5%." style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="6" loext:num-list-format="%6%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="7" loext:num-list-format="%7%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="8" loext:num-list-format="%8%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="9" loext:num-list-format="%9%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:outline-level-style> + <text:outline-level-style text:level="10" loext:num-list-format="%10%" style:num-format=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.048cm" fo:text-indent="-3.048cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:outline-level-style> + </text:outline-style> + <text:list-style style:name="List_20_1" style:display-name="List 1"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.4cm" fo:text-indent="-0.4cm" fo:margin-left="0.4cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" loext:num-list-format="%2%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.801cm" fo:text-indent="-0.4cm" fo:margin-left="0.801cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" loext:num-list-format="%3%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.4cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.6cm" fo:text-indent="-0.4cm" fo:margin-left="1.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" loext:num-list-format="%5%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2cm" fo:text-indent="-0.4cm" fo:margin-left="2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" loext:num-list-format="%6%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.4cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.799cm" fo:text-indent="-0.4cm" fo:margin-left="2.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" loext:num-list-format="%8%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.2cm" fo:text-indent="-0.4cm" fo:margin-left="3.2cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" loext:num-list-format="%9%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.6cm" fo:text-indent="-0.4cm" fo:margin-left="3.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.001cm" fo:text-indent="-0.4cm" fo:margin-left="4.001cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="List_20_2" style:display-name="List 2"> + <text:list-level-style-bullet text:level="1" text:style-name="Numbering_20_Symbols" loext:num-list-format="%1%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.3cm" fo:text-indent="-0.3cm" fo:margin-left="0.3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Numbering_20_Symbols" loext:num-list-format="%2%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.6cm" fo:text-indent="-0.3cm" fo:margin-left="0.6cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Numbering_20_Symbols" loext:num-list-format="%3%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.9cm" fo:text-indent="-0.3cm" fo:margin-left="0.9cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Numbering_20_Symbols" loext:num-list-format="%4%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.199cm" fo:text-indent="-0.3cm" fo:margin-left="1.199cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Numbering_20_Symbols" loext:num-list-format="%5%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.499cm" fo:text-indent="-0.3cm" fo:margin-left="1.499cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Numbering_20_Symbols" loext:num-list-format="%6%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.799cm" fo:text-indent="-0.3cm" fo:margin-left="1.799cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Numbering_20_Symbols" loext:num-list-format="%7%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.101cm" fo:text-indent="-0.3cm" fo:margin-left="2.101cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Numbering_20_Symbols" loext:num-list-format="%8%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.401cm" fo:text-indent="-0.3cm" fo:margin-left="2.401cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Numbering_20_Symbols" loext:num-list-format="%9%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.701cm" fo:text-indent="-0.3cm" fo:margin-left="2.701cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Numbering_20_Symbols" loext:num-list-format="%10%" text:bullet-char="–"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3cm" fo:text-indent="-0.3cm" fo:margin-left="3cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="OpenSymbol"/> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="WW8Num1" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" loext:num-list-format="%1%." style:num-suffix="." text:bullet-char="-"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="2" loext:num-list-format="%2%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" loext:num-list-format="%3%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" loext:num-list-format="%4%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" loext:num-list-format="%5%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" loext:num-list-format="%6%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" loext:num-list-format="%7%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" loext:num-list-format="%8%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" loext:num-list-format="%9%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num2"> + <text:list-level-style-number text:level="1" loext:num-list-format="%1%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" loext:num-list-format="%1%.%2%." style:num-suffix="." style:num-format="1" text:display-levels="2"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.762cm" fo:margin-left="1.397cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" loext:num-list-format="%1%.%2%.%3%." style:num-suffix="." style:num-format="1" text:display-levels="3"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-0.889cm" fo:margin-left="2.159cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" loext:num-list-format="%1%.%2%.%3%.%4%." style:num-suffix="." style:num-format="1" text:display-levels="4"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.143cm" fo:margin-left="3.048cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" loext:num-list-format="%1%.%2%.%3%.%4%.%5%." style:num-suffix="." style:num-format="1" text:display-levels="5"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" fo:text-indent="-1.397cm" fo:margin-left="3.937cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" loext:num-list-format="%6%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" loext:num-list-format="%7%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" loext:num-list-format="%8%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" loext:num-list-format="%9%" style:num-format="" text:start-value="0"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num3" text:consecutive-numbering="true"> + <text:list-level-style-bullet text:level="1" text:style-name="Zeichenformat" loext:num-list-format="%1%." style:num-suffix="." text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Arial"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Zeichenformat" loext:num-list-format="%2%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Zeichenformat" loext:num-list-format="%3%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Zeichenformat" loext:num-list-format="%4%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Zeichenformat" loext:num-list-format="%5%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Zeichenformat" loext:num-list-format="%6%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.635cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Zeichenformat" loext:num-list-format="%7%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Symbol" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Zeichenformat" loext:num-list-format="%8%." style:num-suffix="." text:bullet-char="o"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + <style:text-properties style:font-name="Courier New"/> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Zeichenformat" loext:num-list-format="%9%." style:num-suffix="." text:bullet-char=""> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.635cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + <style:text-properties fo:font-family="Wingdings" style:font-pitch="variable" style:font-charset="x-symbol"/> + </text:list-level-style-bullet> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:list-style style:name="WW8Num4" text:consecutive-numbering="true"> + <text:list-level-style-number text:level="1" text:style-name="Zeichenformat" loext:num-list-format="[%1%]" style:num-prefix="[" style:num-suffix="]" style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="0.635cm" fo:text-indent="-0.635cm" fo:margin-left="0.635cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="2" loext:num-list-format="%2%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="3" loext:num-list-format="%3%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.318cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="4" loext:num-list-format="%4%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="5" loext:num-list-format="%5%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="6" loext:num-list-format="%6%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="7.62cm" fo:text-indent="-0.318cm" fo:margin-left="7.62cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="7" loext:num-list-format="%7%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="8.89cm" fo:text-indent="-0.635cm" fo:margin-left="8.89cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="8" loext:num-list-format="%8%." style:num-suffix="." style:num-format="a" style:num-letter-sync="true"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="10.16cm" fo:text-indent="-0.635cm" fo:margin-left="10.16cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="9" loext:num-list-format="%9%." style:num-suffix="." style:num-format="i"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment" fo:text-align="end"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="11.43cm" fo:text-indent="-0.318cm" fo:margin-left="11.43cm"/> + </style:list-level-properties> + </text:list-level-style-number> + <text:list-level-style-number text:level="10" loext:num-list-format="%10%." style:num-suffix="." style:num-format="1"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-number> + </text:list-style> + <text:notes-configuration text:note-class="footnote" text:citation-style-name="Footnote_20_Symbol" text:citation-body-style-name="Footnote_20_anchor" style:num-format="1" text:start-value="0" text:footnotes-position="page" text:start-numbering-at="document"/> + <text:notes-configuration text:note-class="endnote" style:num-format="i" text:start-value="0"/> + <text:linenumbering-configuration text:number-lines="false" text:offset="0.499cm" style:num-format="1" text:number-position="left" text:increment="5"/> + <style:default-page-layout> + <style:page-layout-properties style:writing-mode="lr-tb" style:layout-grid-standard-mode="true"/> + </style:default-page-layout> + </office:styles> + <office:automatic-styles> + <style:style style:name="P1" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P2" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P3" style:family="paragraph" style:parent-style-name="Header"> + <style:paragraph-properties> + <style:tab-stops> + <style:tab-stop style:position="7.62cm" style:type="center"/> + <style:tab-stop style:position="15.87cm" style:type="right"/> + </style:tab-stops> + </style:paragraph-properties> + <style:text-properties officeooo:paragraph-rsid="00c70c23"/> + </style:style> + <style:style style:name="P4" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0cm" fo:margin-bottom="0cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00a15095" officeooo:paragraph-rsid="00b24c70"/> + </style:style> + <style:style style:name="P5" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P6" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P7" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P8" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac" officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P9" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P10" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P11" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P12" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P13" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P14" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00c54488" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P15" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cdbcae" officeooo:paragraph-rsid="00cdbcae"/> + </style:style> + <style:style style:name="P16" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cf1588"/> + </style:style> + <style:style style:name="P17" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00cfa0ac"/> + </style:style> + <style:style style:name="P18" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P19" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P20" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P21" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P22" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P23" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P24" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P25" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + </style:style> + <style:style style:name="P26" style:family="paragraph" style:parent-style-name="Title" style:master-page-name=""> + <style:paragraph-properties style:page-number="auto"/> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P27" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P28" style:family="paragraph" style:parent-style-name="Text_20_body"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P29" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:paragraph-properties fo:break-before="page"/> + </style:style> + <style:style style:name="P30" style:family="paragraph" style:parent-style-name="Heading_20_1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P31" style:family="paragraph" style:parent-style-name="Subtitle"> + <style:paragraph-properties style:writing-mode="lr-tb"/> + <style:text-properties officeooo:rsid="00d5c2d1" officeooo:paragraph-rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="P32" style:family="paragraph" style:parent-style-name="Subtitle"> + <style:paragraph-properties style:writing-mode="lr-tb"/> + </style:style> + <style:style style:name="P33" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + </style:style> + <style:style style:name="P34" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:margin-top="0.423cm" fo:margin-bottom="0.212cm" style:contextual-spacing="false" fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:paragraph-rsid="00a15095"/> + </style:style> + <style:style style:name="P35" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="List_20_1"> + <style:paragraph-properties fo:text-align="start" style:justify-single-word="false"/> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00d2330d"/> + </style:style> + <style:style style:name="P36" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name=""> + <style:text-properties officeooo:rsid="00d2330d" officeooo:paragraph-rsid="00c54488"/> + </style:style> + <style:style style:name="P37" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P38" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P39" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P40" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d41fec" officeooo:paragraph-rsid="00d41fec"/> + </style:style> + <style:style style:name="P41" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L1"> + <style:text-properties officeooo:rsid="00d47496" officeooo:paragraph-rsid="00d47496"/> + </style:style> + <style:style style:name="P42" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2"> + <style:text-properties officeooo:rsid="00cfb716" officeooo:paragraph-rsid="00cfb716"/> + </style:style> + <style:style style:name="P43" style:family="paragraph" style:parent-style-name="Text_20_body" style:list-style-name="L2"> + <style:text-properties officeooo:rsid="00d0d623" officeooo:paragraph-rsid="00d0d623"/> + </style:style> + <style:style style:name="P44" style:family="paragraph" style:parent-style-name="Title" style:master-page-name="Standard"> + <style:paragraph-properties style:page-number="auto" style:writing-mode="lr-tb"/> + <style:text-properties officeooo:rsid="00cbc3ea" officeooo:paragraph-rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T1" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T2" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T3" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T4" style:family="text"> + <style:text-properties officeooo:rsid="00cbc3ea" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T5" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1" style:font-size-complex="22pt"/> + </style:style> + <style:style style:name="T6" style:family="text"> + <style:text-properties officeooo:rsid="00a7512c"/> + </style:style> + <style:style style:name="T7" style:family="text"> + <style:text-properties fo:font-weight="normal" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T8" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="000f7635" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T9" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="006c9f57" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T10" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00a15095" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T11" style:family="text"> + <style:text-properties fo:font-weight="normal" officeooo:rsid="00d41fec" style:font-weight-asian="normal" style:font-weight-complex="normal"/> + </style:style> + <style:style style:name="T12" style:family="text"> + <style:text-properties officeooo:rsid="000f7635"/> + </style:style> + <style:style style:name="T13" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt"/> + </style:style> + <style:style style:name="T14" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T15" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T16" style:family="text"> + <style:text-properties style:font-name="Times New Roman" fo:font-size="10pt" officeooo:rsid="00cfa0ac"/> + </style:style> + <style:style style:name="T17" style:family="text"> + <style:text-properties officeooo:rsid="00a4215b"/> + </style:style> + <style:style style:name="T18" style:family="text"> + <style:text-properties officeooo:rsid="00a59973"/> + </style:style> + <style:style style:name="T19" style:family="text"> + <style:text-properties officeooo:rsid="00b24c70"/> + </style:style> + <style:style style:name="T20" style:family="text"> + <style:text-properties officeooo:rsid="00cf1588"/> + </style:style> + <style:style style:name="T21" style:family="text"> + <style:text-properties fo:font-size="10pt" officeooo:rsid="00cdbcae"/> + </style:style> + <style:style style:name="T22" style:family="text"> + <style:text-properties officeooo:rsid="00d41fec"/> + </style:style> + <style:style style:name="T23" style:family="text"> + <style:text-properties officeooo:rsid="00d47496"/> + </style:style> + <style:style style:name="T24" style:family="text"> + <style:text-properties officeooo:rsid="00d5c2d1"/> + </style:style> + <text:list-style style:name="L1"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" loext:num-list-format="%2%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" loext:num-list-format="%3%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" loext:num-list-format="%5%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" loext:num-list-format="%6%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" loext:num-list-format="%8%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" loext:num-list-format="%9%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <text:list-style style:name="L2"> + <text:list-level-style-bullet text:level="1" text:style-name="Bullet_20_Symbols" loext:num-list-format="%1%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.27cm" fo:text-indent="-0.635cm" fo:margin-left="1.27cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="2" text:style-name="Bullet_20_Symbols" loext:num-list-format="%2%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="1.905cm" fo:text-indent="-0.635cm" fo:margin-left="1.905cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="3" text:style-name="Bullet_20_Symbols" loext:num-list-format="%3%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="2.54cm" fo:text-indent="-0.635cm" fo:margin-left="2.54cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="4" text:style-name="Bullet_20_Symbols" loext:num-list-format="%4%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.175cm" fo:text-indent="-0.635cm" fo:margin-left="3.175cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="5" text:style-name="Bullet_20_Symbols" loext:num-list-format="%5%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="3.81cm" fo:text-indent="-0.635cm" fo:margin-left="3.81cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="6" text:style-name="Bullet_20_Symbols" loext:num-list-format="%6%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="4.445cm" fo:text-indent="-0.635cm" fo:margin-left="4.445cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="7" text:style-name="Bullet_20_Symbols" loext:num-list-format="%7%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.08cm" fo:text-indent="-0.635cm" fo:margin-left="5.08cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="8" text:style-name="Bullet_20_Symbols" loext:num-list-format="%8%" text:bullet-char="◦"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="5.715cm" fo:text-indent="-0.635cm" fo:margin-left="5.715cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="9" text:style-name="Bullet_20_Symbols" loext:num-list-format="%9%" text:bullet-char="▪"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.35cm" fo:text-indent="-0.635cm" fo:margin-left="6.35cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + <text:list-level-style-bullet text:level="10" text:style-name="Bullet_20_Symbols" loext:num-list-format="%10%" text:bullet-char="•"> + <style:list-level-properties text:list-level-position-and-space-mode="label-alignment"> + <style:list-level-label-alignment text:label-followed-by="listtab" text:list-tab-stop-position="6.985cm" fo:text-indent="-0.635cm" fo:margin-left="6.985cm"/> + </style:list-level-properties> + </text:list-level-style-bullet> + </text:list-style> + <style:page-layout style:name="pm1"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="3.5cm" fo:margin-right="3.5cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style> + <style:header-footer-properties fo:min-height="0.998cm" fo:margin-left="0cm" fo:margin-right="0cm" fo:margin-bottom="0.499cm" fo:border-top="none" fo:border-bottom="0.06pt solid #000000" fo:border-left="none" fo:border-right="none" fo:padding="0.049cm" style:shadow="none" style:dynamic-spacing="false"/> + </style:header-style> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm2"> + <style:page-layout-properties fo:page-width="21.001cm" fo:page-height="29.7cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1.27cm" fo:margin-bottom="1.27cm" fo:margin-left="2.54cm" fo:margin-right="2.54cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="39" style:layout-grid-base-height="0.635cm" style:layout-grid-ruby-height="0cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.353cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm3"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="1cm" fo:margin-bottom="1cm" fo:margin-left="2cm" fo:margin-right="1cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:width="0.018cm" style:distance-before-sep="0.101cm" style:distance-after-sep="0.101cm" style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:page-layout style:name="pm4"> + <style:page-layout-properties fo:page-width="21.59cm" fo:page-height="27.94cm" style:num-format="1" style:print-orientation="portrait" fo:margin-top="2cm" fo:margin-bottom="2cm" fo:margin-left="2cm" fo:margin-right="2cm" style:writing-mode="lr-tb" style:layout-grid-color="#c0c0c0" style:layout-grid-lines="20" style:layout-grid-base-height="0.706cm" style:layout-grid-ruby-height="0.353cm" style:layout-grid-mode="none" style:layout-grid-ruby-below="false" style:layout-grid-print="false" style:layout-grid-display="false" style:layout-grid-base-width="0.706cm" style:layout-grid-snap-to="true" style:footnote-max-height="0cm" loext:margin-gutter="0cm"> + <style:footnote-sep style:line-style="solid" style:adjustment="left" style:rel-width="25%" style:color="#000000"/> + </style:page-layout-properties> + <style:header-style/> + <style:footer-style/> + </style:page-layout> + <style:style style:name="dp1" style:family="drawing-page"> + <style:drawing-page-properties draw:background-size="full"/> + </style:style> + </office:automatic-styles> + <office:master-styles> + <style:master-page style:name="Standard" style:page-layout-name="pm1" draw:style-name="dp1"> + <style:header> + <text:p text:style-name="P1"><text:span text:style-name="T1">SOFA Toolbox for Matlab/Octave</text:span><text:span text:style-name="T2"> </text:span><text:title>version 2.0</text:title><text:tab/><text:span text:style-name="T3"><text:tab/>Page: </text:span><text:span text:style-name="T3"><text:page-number text:select-page="current">2</text:page-number></text:span></text:p> + </style:header> + </style:master-page> + <style:master-page style:name="First_20_Page" style:display-name="First Page" style:page-layout-name="pm2" draw:style-name="dp1" style:next-style-name="Standard"/> + <style:master-page style:name="HTML" style:page-layout-name="pm3" draw:style-name="dp1"/> + <style:master-page style:name="Footnote" style:page-layout-name="pm4" draw:style-name="dp1"/> + <style:master-page style:name="Endnote" style:page-layout-name="pm4" draw:style-name="dp1"/> + </office:master-styles> + <office:body> + <office:text text:use-soft-page-breaks="true"> + <office:forms form:automatic-focus="false" form:apply-design-mode="false"/> + <text:sequence-decls> + <text:sequence-decl text:display-outline-level="0" text:name="Illustration"/> + <text:sequence-decl text:display-outline-level="0" text:name="Table"/> + <text:sequence-decl text:display-outline-level="0" text:name="Text"/> + <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/> + <text:sequence-decl text:display-outline-level="0" text:name="Figure"/> + <text:sequence-decl text:display-outline-level="0" text:name="AutoNr"/> + </text:sequence-decls> + <text:p text:style-name="P44">SOFA <text:span text:style-name="T24">Toolbox for </text:span>Matlab/Octave</text:p> + <text:p text:style-name="P31">(previously SOFA API_MO)</text:p> + <text:p text:style-name="Subtitle"><text:span text:style-name="T12">Piotr Majdak<text:line-break/></text:span><text:span text:style-name="T8">Acoustics Research Institute </text:span><text:span text:style-name="T11">(ARI)</text:span><text:span text:style-name="T8">, <text:line-break/>Austrian Academy of Sciences </text:span><text:span text:style-name="T11">(OeAW)</text:span><text:span text:style-name="T8"><text:line-break/></text:span><text:span text:style-name="T9">Vienna</text:span><text:span text:style-name="T8">, Austria</text:span><text:span text:style-name="T12"><text:line-break/></text:span><text:span text:style-name="T10"><</text:span><text:span text:style-name="T7">piotr@majdak.com</text:span><text:span text:style-name="T10">></text:span></text:p> + <text:p text:style-name="P32"><text:span text:style-name="T18">This document contains preliminary remarks on the <text:line-break/></text:span><text:span text:style-name="T24">SOFA Toolbox</text:span><text:span text:style-name="T18"> </text:span><text:span text:style-name="T18"><text:title>version 2.0</text:title></text:span><text:span text:style-name="T18">.</text:span></text:p> + <text:p text:style-name="P4"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T19">Further c</text:span></text:span><text:span text:style-name="Strong_20_Emphasis">ontributors</text:span>:</text:p> + <text:list xml:id="list301348430" text:style-name="List_20_1"> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="Strong_20_Emphasis">Hagen Wierstorf</text:span> (Telekom Innovation Laboratories, Technical University of Berlin, Berlin, Germany) hagen.wierstorf@telekom.de</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P34"><text:span text:style-name="Strong_20_Emphasis">Harald Ziegelwanger</text:span> (Acoustics Research Institute<text:span text:style-name="T12">, Austrian Academy of Sciences, Vienna, Austria) h.ziegelwanger@me.com</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P33"><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T17">Michael Mihocic</text:span></text:span> (Acoustics Research Institute, Austrian Academy of Sciences, Vienna, Austria) <text:span text:style-name="T17">michael.mihocic@oeaw.ac.at</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P35"><text:span text:style-name="Strong_20_Emphasis">Wolfgang Hrauda </text:span><text:span text:style-name="Strong_20_Emphasis"><text:span text:style-name="T7">wolfgang.hrauda@gmx.at</text:span></text:span></text:p> + </text:list-item> + </text:list> + <text:h text:style-name="P36" text:outline-level="2"/> + <text:h text:style-name="P11" text:outline-level="1">STARTING the <text:span text:style-name="T24">Toolbox</text:span></text:h> + <text:p text:style-name="Text_20_body"><text:span text:style-name="Source_20_Text"><text:span text:style-name="T21">SOFAstart</text:span></text:span> compiles the conventions (stored in directory conventions as CSV files) to Matlab files and starts the <text:span text:style-name="T24">Toolbox</text:span>.</text:p> + <text:p text:style-name="Text_20_body">More information in readme.txt <text:span text:style-name="T22">or help SOFAstart.</text:span></text:p> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Demonstrations</text:h> + <text:p text:style-name="Text_20_body">In the directory “demos”, some demonstrations of the functionality of the Toolbox are provided. This is the first place to get familiar with the structure of the Toolbox.</text:p> + <text:p text:style-name="P24">Note that for the demonstration of conversion functions, you will most probably need to download some non-SOFA HRTF files first. See readme.txt files in the HRTF directories of the corresponding non-SOFA format.</text:p> + <text:h text:style-name="P9" text:outline-level="1">Structure of the SOFA OBJECT</text:h> + <text:p text:style-name="P10">All the SOFA information is stored in the a variable which we call SOFA object here. <text:span text:style-name="T22">Such an object is, for example, returned by the function SOFAload. </text:span>In that object:</text:p> + <text:list xml:id="list2273856870" text:style-name="L1"> + <text:list-item> + <text:p text:style-name="P37">“GLOBAL_” <text:span text:style-name="T22">are all g</text:span>lobal attributes. <text:span text:style-name="T23">Use prefix GLOBAL_ to add your global attributes.</text:span> </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P40">Variables are stored with their names as they are.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37"><text:span text:style-name="T22">An a</text:span>ttribute Y of a variable X is stored as X_Y. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P38">“Data.” <text:span text:style-name="T22">is a </text:span>separate structure <text:span text:style-name="T22">containing </text:span>the SOFA data. </text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P37">“PRIVATE” <text:span text:style-name="T22">is a</text:span> structure with private data for application use. <text:span text:style-name="T22">Here you can store your private variables which belong to the SOFA object. P</text:span>rivate <text:span text:style-name="T22">variables</text:span> won't be saved when saving <text:span text:style-name="T22">the</text:span> object <text:span text:style-name="T22">as a SOFA file.</text:span></text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">“API” <text:span text:style-name="T22">contains </text:span>internal variables <text:span text:style-name="T22">of the </text:span><text:span text:style-name="T24">Toolbox </text:span><text:span text:style-name="T22">API. Do not modify them, use SOFAupdateDimensions() to update them according to your data. These variables</text:span> are <text:span text:style-name="T23">useful for handling the SOFA data</text:span>:</text:p> + <text:list> + <text:list-item> + <text:p text:style-name="P39">API.N, API.M, etc (all SOFA dimensions): store the size of a dimension</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P39">API.Dimensions: dimensions of SOFA variables</text:p> + </text:list-item> + </text:list> + </text:list-item> + <text:list-item> + <text:p text:style-name="P41">Use SOFAaddVariable() to add a new variable. </text:p> + </text:list-item> + </text:list> + <text:h text:style-name="Heading_20_1" text:outline-level="1">Further resources</text:h> + <text:p text:style-name="P18">Further resources can be found:</text:p> + <text:list xml:id="list3009974912" text:style-name="L2"> + <text:list-item> + <text:p text:style-name="P42">SOFAtoolbox/readme.txt provides a short description of the SOFAtoolbox.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">SOFAtoolbox/history.txt provides the history of the development and release notes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">doc/specs provides specifications of the currently supported SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/SOFA stores SOFA files. Per default, it mirrors http://sofacoustics.org/data.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/SOFA/sofa<text:span text:style-name="T24">toolbox</text:span>_test: here, the automatically created SOFA files will be saved for testing purposes.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P43">HRTFs/other directories: directories containing HRTF files stored in other formats than SOFA.</text:p> + </text:list-item> + <text:list-item> + <text:p text:style-name="P42">http://sofaconventions.org provides the most recent information on SOFA.</text:p> + </text:list-item> + </text:list> + </office:text> + </office:body> +</office:document> \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/license.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..355bc6cdd47000634dc919a2f65235c850219a88 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/SOFAtoolbox-master/license.txt @@ -0,0 +1,287 @@ +EUROPEAN UNION PUBLIC LICENCE v. 1.2 +EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined +below) which is provided under the terms of this Licence. Any use of the Work, +other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). + +The Work is provided under the terms of this Licence when the Licensor (as +defined below) has placed the following notice immediately following the +copyright notice for the Work: + + Licensed under the EUPL + +or has expressed by any other means his willingness to license under the EUPL. + +1. Definitions + +In this Licence, the following terms have the following meaning: + +- ‘The Licence’: this Licence. + +- ‘The Original Work’: the work or software distributed or communicated by the + Licensor under this Licence, available as Source Code and also as Executable + Code as the case may be. + +- ‘Derivative Works’: the works or software that could be created by the + Licensee, based upon the Original Work or modifications thereof. This Licence + does not define the extent of modification or dependence on the Original Work + required in order to classify a work as a Derivative Work; this extent is + determined by copyright law applicable in the country mentioned in Article 15. + +- ‘The Work’: the Original Work or its Derivative Works. + +- ‘The Source Code’: the human-readable form of the Work which is the most + convenient for people to study and modify. + +- ‘The Executable Code’: any code which has generally been compiled and which is + meant to be interpreted by a computer as a program. + +- ‘The Licensor’: the natural or legal person that distributes or communicates + the Work under the Licence. + +- ‘Contributor(s)’: any natural or legal person who modifies the Work under the + Licence, or otherwise contributes to the creation of a Derivative Work. + +- ‘The Licensee’ or ‘You’: any natural or legal person who makes any usage of + the Work under the terms of the Licence. + +- ‘Distribution’ or ‘Communication’: any act of selling, giving, lending, + renting, distributing, communicating, transmitting, or otherwise making + available, online or offline, copies of the Work or providing access to its + essential functionalities at the disposal of any other natural or legal + person. + +2. Scope of the rights granted by the Licence + +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +sublicensable licence to do the following, for the duration of copyright vested +in the Original Work: + +- use the Work in any circumstance and for all usage, +- reproduce the Work, +- modify the Work, and make Derivative Works based upon the Work, +- communicate to the public, including the right to make available or display + the Work or copies thereof to the public and perform publicly, as the case may + be, the Work, +- distribute the Work or copies thereof, +- lend and rent the Work or copies thereof, +- sublicense rights in the Work or copies thereof. + +Those rights can be exercised on any media, supports and formats, whether now +known or later invented, as far as the applicable law permits so. + +In the countries where moral rights apply, the Licensor waives his right to +exercise his moral right to the extent allowed by law in order to make effective +the licence of the economic rights here above listed. + +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to +any patents held by the Licensor, to the extent necessary to make use of the +rights granted on the Work under this Licence. + +3. Communication of the Source Code + +The Licensor may provide the Work either in its Source Code form, or as +Executable Code. If the Work is provided as Executable Code, the Licensor +provides in addition a machine-readable copy of the Source Code of the Work +along with each copy of the Work that the Licensor distributes or indicates, in +a notice following the copyright notice attached to the Work, a repository where +the Source Code is easily and freely accessible for as long as the Licensor +continues to distribute or communicate the Work. + +4. Limitations on copyright + +Nothing in this Licence is intended to deprive the Licensee of the benefits from +any exception or limitation to the exclusive rights of the rights owners in the +Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5. Obligations of the Licensee + +The grant of the rights mentioned above is subject to some restrictions and +obligations imposed on the Licensee. Those obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or +trademarks notices and all notices that refer to the Licence and to the +disclaimer of warranties. The Licensee must include a copy of such notices and a +copy of the Licence with every copy of the Work he/she distributes or +communicates. The Licensee must cause any Derivative Work to carry prominent +notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the +Original Works or Derivative Works, this Distribution or Communication will be +done under the terms of this Licence or of a later version of this Licence +unless the Original Work is expressly distributed only under this version of the +Licence — for example by communicating ‘EUPL v. 1.2 only’. The Licensee +(becoming Licensor) cannot offer or impose any additional terms or conditions on +the Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative +Works or copies thereof based upon both the Work and another work licensed under +a Compatible Licence, this Distribution or Communication can be done under the +terms of this Compatible Licence. For the sake of this clause, ‘Compatible +Licence’ refers to the licences listed in the appendix attached to this Licence. +Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible +Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, +the Licensee will provide a machine-readable copy of the Source Code or indicate +a repository where this Source will be easily and freely available for as long +as the Licensee continues to distribute or communicate the Work. + +Legal Protection: This Licence does not grant permission to use the trade names, +trademarks, service marks, or names of the Licensor, except as required for +reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6. Chain of Authorship + +The original Licensor warrants that the copyright in the Original Work granted +hereunder is owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each Contributor warrants that the copyright in the modifications he/she brings +to the Work are owned by him/her or licensed to him/her and that he/she has the +power and authority to grant the Licence. + +Each time You accept the Licence, the original Licensor and subsequent +Contributors grant You a licence to their contributions to the Work, under the +terms of this Licence. + +7. Disclaimer of Warranty + +The Work is a work in progress, which is continuously improved by numerous +Contributors. It is not a finished work and may therefore contain defects or +‘bugs’ inherent to this type of development. + +For the above reason, the Work is provided under the Licence on an ‘as is’ basis +and without warranties of any kind concerning the Work, including without +limitation merchantability, fitness for a particular purpose, absence of defects +or errors, accuracy, non-infringement of intellectual property rights other than +copyright as stated in Article 6 of this Licence. + +This disclaimer of warranty is an essential part of the Licence and a condition +for the grant of any rights to the Work. + +8. Disclaimer of Liability + +Except in the cases of wilful misconduct or damages directly caused to natural +persons, the Licensor will in no event be liable for any direct or indirect, +material or moral, damages of any kind, arising out of the Licence or of the use +of the Work, including without limitation, damages for loss of goodwill, work +stoppage, computer failure or malfunction, loss of data or any commercial +damage, even if the Licensor has been advised of the possibility of such damage. +However, the Licensor will be liable under statutory product liability laws as +far such laws apply to the Work. + +9. Additional agreements + +While distributing the Work, You may choose to conclude an additional agreement, +defining obligations or services consistent with this Licence. However, if +accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, +and only if You agree to indemnify, defend, and hold each Contributor harmless +for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10. Acceptance of the Licence + +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ +placed under the bottom of a window displaying the text of this Licence or by +affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable +acceptance of this Licence and all of its terms and conditions. + +Similarly, you irrevocably accept this Licence and all of its terms and +conditions by exercising any rights granted to You by Article 2 of this Licence, +such as the use of the Work, the creation by You of a Derivative Work or the +Distribution or Communication by You of the Work or copies thereof. + +11. Information to the public + +In case of any Distribution or Communication of the Work by means of electronic +communication by You (for example, by offering to download the Work from a +remote location) the distribution channel or media (for example, a website) must +at least provide to the public the information requested by the applicable law +regarding the Licensor, the Licence and the way it may be accessible, concluded, +stored and reproduced by the Licensee. + +12. Termination of the Licence + +The Licence and the rights granted hereunder will terminate automatically upon +any breach by the Licensee of the terms of the Licence. + +Such a termination will not terminate the licences of any person who has +received the Work from the Licensee under the Licence, provided such persons +remain in full compliance with the Licence. + +13. Miscellaneous + +Without prejudice of Article 9 above, the Licence represents the complete +agreement between the Parties as to the Work. + +If any provision of the Licence is invalid or unenforceable under applicable +law, this will not affect the validity or enforceability of the Licence as a +whole. Such provision will be construed or reformed so as necessary to make it +valid and enforceable. + +The European Commission may publish other linguistic versions or new versions of +this Licence or updated versions of the Appendix, so far this is required and +reasonable, without reducing the scope of the rights granted by the Licence. New +versions of the Licence will be published with a unique version number. + +All linguistic versions of this Licence, approved by the European Commission, +have identical value. Parties can take advantage of the linguistic version of +their choice. + +14. Jurisdiction + +Without prejudice to specific agreement between parties, + +- any litigation resulting from the interpretation of this License, arising + between the European Union institutions, bodies, offices or agencies, as a + Licensor, and any Licensee, will be subject to the jurisdiction of the Court + of Justice of the European Union, as laid down in article 272 of the Treaty on + the Functioning of the European Union, + +- any litigation arising between other parties and resulting from the + interpretation of this License, will be subject to the exclusive jurisdiction + of the competent court where the Licensor resides or conducts its primary + business. + +15. Applicable Law + +Without prejudice to specific agreement between parties, + +- this Licence shall be governed by the law of the European Union Member State + where the Licensor has his seat, resides or has his registered office, + +- this licence shall be governed by Belgian law if the Licensor has no seat, + residence or registered office inside a European Union Member State. + +Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: + +- GNU General Public License (GPL) v. 2, v. 3 +- GNU Affero General Public License (AGPL) v. 3 +- Open Software License (OSL) v. 2.1, v. 3.0 +- Eclipse Public License (EPL) v. 1.0 +- CeCILL v. 2.0, v. 2.1 +- Mozilla Public Licence (MPL) v. 2 +- GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +- Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for + works other than software +- European Union Public Licence (EUPL) v. 1.1, v. 1.2 +- Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong + Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above +licences without producing a new version of the EUPL, as long as they provide +the rights granted in Article 2 of this Licence and protect the covered Source +Code from exclusive appropriation. + +All other changes or additions to this Appendix require the production of a new +EUPL version. \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/license.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/license.txt new file mode 100644 index 0000000000000000000000000000000000000000..16f919d64f03df006bafd9563a0a77911825df44 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/license.txt @@ -0,0 +1,24 @@ +Copyright (c) 1997, Christophe COUVREUR +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave.zip b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave.zip new file mode 100644 index 0000000000000000000000000000000000000000..8746175eed63c532d30a0b4cd0ff875b75fa6c4a Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave.zip differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/README b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/README new file mode 100644 index 0000000000000000000000000000000000000000..847f4cdaf988a6e0a30e67f77a364dac6df89c1c --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/README @@ -0,0 +1,99 @@ +This series of M-files generates A-weigthing, C-weighting, octave and +one-third-octave digital filters. These filters are commonly used in +acoustics, for example, in noise control. + +The implementation is based on the following standards: + + * IEC/CD 1672: Electroacoustics-Sound Level Meters, IEC, Geneva, Nov. 1996, + for A- and C-weighting filters. + + * ANSI S1.1-1986 (ASA 65-1986): Specifications for Octave-Band + and Fractional-Octave-Band Analog and Digital Filters, ASA, New York, 1993, + for octave and one-third-octave filters. + +The following M-files are available: + + octave.tar.gz Compressed Unix tar archive containing all of the files below. + README This file. + adsgn.m Design of a A-weighting filter. + aspec.m Plots a filter characteristics vs. A-weighting specifications. + cdsgn.m Design of a A-weighting filter. + cspec.m Plots a filter characteristics vs. C-weighting specifications. + octdsgn.m Design of an octave filter. + octspec.m Plots an octave filter characteristics. + oct3dsgn.m Design of a one-third-octave filter. + oct3spec.m Plots a one-third-octave filter characteristics. + oct3bank.m Simple one-third-octave filter bank. + filtbank.m One-third-octave band frequency analyser. + leq.m Computes the sequence of short-time RMS powers (Leq) of a signal. + bankdisp.m Display filterbank power spectrum in 'bar' form. + +The M-files have been tested under MATLAB 4.1 and MATLAB 5.1. +They should normally work under both versions of MATLAB if you disregard +the warnings that might be issued in some cases. If it is necessary +to make changes to a M-file to allow it to work with different versions +of MATLAB, just uncomment the adequate lines of code (alternate code +is provided in the M-file). + +-- Christophe Couvreur (couvreur@thor.fpms.ac.be), August 1997. + + +Sample utilisations of the M-files: +---------------------------------- + +1) Conception of an A-weighting filter and verification of its characteristics: + + >> Fs = 44100; + >> [B,A] = adsgn(Fs); + >> aspec(B,A,Fs); + +2) Conception of a one-third-octave filter and verification of its characteristics: + + >> Fs = 44100; + >> Fc = 4000; + >> [B,A] = oct3dsgn(Fc,Fs); + >> oct3spec(B,A,Fs,Fc,'ansi'); + +3) Construction of an octave or one-third-octave filter bank: + + See the simple implementation (fixed sampling frequency) in OCT3BANK. + Note that a multirate implementation is used to avoid problems + with the low frequency bands. + +4) Analysis of a signal with FILTBANK: computation of time-varying A-weighted + one-third-octave Leq spectrum and display as a waterfall plot. + It is assumed that the signal is stored in the variable x. + The frame length for the analysis is T = 100ms. + + >> Fs = 48000; + >> T = 100e-3; + >> [B,A] = adsgn(Fs); + >> x = filter(B,A,x); + >> [P,F] = filtbank(x,Fs,T,'extended'); + >> waterfall(P'); + >> zlabel('Level [dB]'); + >> ylabel('Frame #'); + >> xlabel('Frequency band'); + >> set(gca,'XTick',[2:3:length(F)]); + >> set(gca,'XTickLabel',F(2:3:length(F))); + + +Contact & Comments: +------------------ + + Dr Ir Christophe Couvreur + Research Assistant, Belgian National Fund for Scientific Research + Department of Physics + Faculte Polytechnique de Mons + Rue de Houdain 9 Ph. +32 65 374042 + B-7000 Mons (Belgium) FAX +32 65 374045 + E-mail: Christophe.Couvreur@fpms.ac.be + WWW: http://thor.fpms.ac.be/~couvreur/ + + + + + + + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/adsgn.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/adsgn.m new file mode 100644 index 0000000000000000000000000000000000000000..c2952bfe2f0e66e32604228b53e20cc388072d59 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/adsgn.m @@ -0,0 +1,33 @@ +function [B,A] = adsgn(Fs); +% ADSGN Design of a A-weighting filter. +% [B,A] = ADSGN(Fs) designs a digital A-weighting filter for +% sampling frequency Fs. Usage: Y = FILTER(B,A,X). +% Warning: Fs should normally be higher than 20 kHz. For example, +% Fs = 48000 yields a class 1-compliant filter. +% +% Requires the Signal Processing Toolbox. +% +% See also ASPEC, CDSGN, CSPEC. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 20, 1997, 10:00am. + +% References: +% [1] IEC/CD 1672: Electroacoustics-Sound Level Meters, Nov. 1996. + + +% Definition of analog A-weighting filter according to IEC/CD 1672. +f1 = 20.598997; +f2 = 107.65265; +f3 = 737.86223; +f4 = 12194.217; +A1000 = 1.9997; +pi = 3.14159265358979; +NUMs = [ (2*pi*f4)^2*(10^(A1000/20)) 0 0 0 0 ]; +DENs = conv([1 +4*pi*f4 (2*pi*f4)^2],[1 +4*pi*f1 (2*pi*f1)^2]); +DENs = conv(conv(DENs,[1 2*pi*f3]),[1 2*pi*f2]); + +% Use the bilinear transformation to get the digital filter. +[B,A] = bilinear(NUMs,DENs,Fs); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/aspec.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/aspec.m new file mode 100644 index 0000000000000000000000000000000000000000..18006d21c21302acf2e46f144560a09429a3405d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/aspec.m @@ -0,0 +1,47 @@ +function aspec(B,A,Fs); +% ASPEC Plots a filter characteristics vs. A-weighting specifications. +% ASPEC(B,A,Fs) plots the attenuation of the filter defined by B and A +% with sampling frequency Fs against the specifications for class 1 +% and class 2 A-weighting filters. +% +% See also ADSGN, CDSGN, CSPEC. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 26, 1997, 10:00am. + +% References: +% [1] IEC/CD 1672: Electroacoustics-Sound Level Meters, Nov. 1996. + + +if (nargin ~= 3) + error('Invalide number of arguments.'); +end + +N = 512; +W = 2*pi*logspace(log10(10),log10(Fs/2),N); +H = freqz(B,A,W/Fs); +fref = [10, 12.5 16 20, 25 31.5 40, 50 63 80, 100 125 160, 200 250 315, ... + 400 500 630, 800 1000 1250, 1600 2000 2500, 3150 4000 5000, ... + 6300 8000 10000, 12500 16000 20000 ]; +Agoal = [-70.4, -63.4 -56.7 -50.5, -44.7 -39.4 -34.6, -30.2 -26.2 -22.5, ... + -19.1 -16.1 -13.4, -10.9 -8.6 -6.6, -4.8 -3.2 -1.9, -.8 0 .6, ... + 1 1.2 1.3, 1.2, 1 .5, -.1 -1.1 -2.5, -4.3 -6.6 -9.3 ]; +up1 = [ 3, .25 2 2, 2 1.5 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 0.7 1, ... + 1 1 1, 1 1 1.5, 1.5 1.5 2, 2 2.5 3 ]; +low1 = [ inf, inf 4 2, 1.5 1.5 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 0.7 1, ... + 1 1 1, 1 1 1.5, 2 2.5 3, 5 8 inf ]; +up2 = [ 5, 5 5 3, 3 3 2, 2 2 2, 1.5 1.5 1.5, 1.5 1.5 1.5, 1.5 1.5 1.5, ... + 1.5 1 1.5, 2 2 2.5, 2.5 3 3.5, 4.5 5 5, 5 5 5 ]; +low2 = [ inf, inf inf 3, 3 3 2, 2 2 2, 1.5 1.5 1.5, 1.5 1.5 1.5, ... + 1.5 1.5 1.5, 1.5 1 1.5, 2,2 2.5, 2.5 3 3.5, 4.5 5 inf, inf inf inf ]; +clf; +semilogx(W/2/pi,20*log10(abs(H)),'-',fref,Agoal+up1,'--',fref,Agoal+up2,':'); +hold on +semilogx(W/2/pi,20*log10(abs(H)),'-',fref,Agoal-low1,'--',fref,Agoal-low2,':'); +hold off +xlabel('Frequency [Hz]'); ylabel('Gain [dB]'); +title(['A-weighting, Fs = ',int2str(Fs),' Hz']); +axis([fref(1) max(fref(34),Fs/2) -75 5]); +legend('Filter','Class 1','Class 2',0); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/bankdisp.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/bankdisp.m new file mode 100644 index 0000000000000000000000000000000000000000..9e45ccb00b2fcf79b89297615b4fc4001d9e4337 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/bankdisp.m @@ -0,0 +1,53 @@ +function h = bankdisp(P,F,Pmin,Pmax); +% BANKDISP Display filterbank power spectrum in 'bar' form. +% BANKDISP(P,F) display the power spectrum P with one bar for +% each frequency band in F. P should already be in dB. +% P and F must be vectors of same sizes. Some frequency labels +% can be omitted by using null elements in F. +% Example: F = [ ..., 0 500 0, 0 1000 0, ... ] can be used to +% label only the octave bands in a one-third-octave spectrum P. +% +% BANKDISP(P,F,Pmin,Pmax) can be used to specify explicitly the limits +% of the Y axis. If min(P) < 0, this version avoid 'hanging' bars. +% +% See also FILTBANK. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 27, 1997, 9:00am. + +N = length(F); +if (nargin == 4) + if (Pmin < 0) + H = bar(P-Pmin); + axis([0 N+1 0 Pmax-Pmin]); +% YTickLabels = get(gca,'YTickLabels'); % MATLAB 4.1 +% NewYTickLabels = str2num(YTickLabels) + Pmin; +% set(gca,'YTickLabels',NewYTickLabels); + YTickLabel = get(gca,'YTickLabel'); % MATLAB 5.1 + NewYTickLabel = str2num(YTickLabel) + Pmin; + set(gca,'YTickLabel',NewYTickLabel); + else + H = bar(P); + axis([0 N+1 Pmin Pmax]); + end +else + H = bar(P); + ax = axis; + axis([0 N+1 ax(3) ax(4)]); +end +ticks = find(F > 0); +set(gca,'XTick',ticks); % Label frequency axis. +%set(gca,'XTickLabels',F(ticks)); % MATLAB 4.1 +set(gca,'XTickLabel',F(ticks)); % MATLAB 5.1 +xlabel('Frequency band [Hz]'); +ylabel('Level [dB]'); + +if (nargout ~= 0) + h = H; +end + + + + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/cdsgn.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/cdsgn.m new file mode 100644 index 0000000000000000000000000000000000000000..a47141071e833df068b3f5f349a259d8e45c0d8a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/cdsgn.m @@ -0,0 +1,30 @@ +function [B,A] = cdsgn(Fs); +% CDSGN Design of a A-weighting filter. +% [B,A] = CDSGN(Fs) designs a digital A-weighting filter for +% sampling frequency Fs. Usage: Y = FILTER(B,A,X). +% Warning: Fs should normally be higher than 20 kHz. For example, +% Fs = 48000 yields a class 1-compliant filter. +% +% Requires the Signal Processing Toolbox. +% +% See also CSPEC, ADSGN, ASPEC. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 20, 1997, 10:10am. + +% References: +% [1] IEC/CD 1672: Electroacoustics-Sound Level Meters, Nov. 1996. + + +% Definition of analog C-weighting filter according to IEC/CD 1672. +f1 = 20.598997; +f4 = 12194.217; +C1000 = 0.0619; +pi = 3.14159265358979; +NUMs = [ (2*pi*f4)^2*(10^(C1000/20)) 0 0 ]; +DENs = conv([1 +4*pi*f4 (2*pi*f4)^2],[1 +4*pi*f1 (2*pi*f1)^2]); + +% Use the bilinear transformation to get the digital filter. +[B,A] = bilinear(NUMs,DENs,Fs); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/cspec.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/cspec.m new file mode 100644 index 0000000000000000000000000000000000000000..c8946cab4b70256a54d116ed9bd100085824eb3b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/cspec.m @@ -0,0 +1,48 @@ +function cspec(B,A,Fs); +% CSPEC Plots a filter characteristics vs. C-weighting specifications. +% CSPEC(B,A,Fs) plots the attenuation of the filter defined by B and A +% with sampling frequency Fs against the specifications for class 1 and +% class 2 C-weighting filters. +% +% See also CDSGN, ADSGN, ASPEC. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 26, 1997, 10:00am. + +% References: +% [1] IEC/CD 1672: Electroacoustics-Sound Level Meters, Nov. 1996. + + +if (nargin ~= 3) + error('Invalide number of arguments.'); +end + +N = 512; +W = 2*pi*logspace(log10(10),log10(Fs/2),N); +H = freqz(B,A,W/Fs); +fref = [10, 12.5 16 20, 25 31.5 40, 50 63 80, 100 125 160, 200 250 315, ... + 400 500 630, 800 1000 1250, 1600 2000 2500, 3150 4000 5000, ... + 6300 8000 10000, 12500 16000 20000 ]; +Cgoal = [ -14.3, -11.2 -8.5 -6.2, -4.4 -3.0 -2.0, -1.3 -.8 -.5, ... + -.3 -.2 -.1, 0 0 0, 0 0 0, 0 0 0, -.1 -.2 -.3, -.5 -.8 -1.3, ... + -2.0 -3.0 -4.4, -6.2 -8.5 -11.2 ]; +up1 = [ 3, .25 2 2, 2 1.5 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 0.7 1, ... + 1 1 1, 1 1 1.5, 1.5 1.5 2, 2 2.5 3 ]; +low1 = [ inf, inf 4 2, 1.5 1.5 1, 1 1 1, 1 1 1, 1 1 1, 1 1 1, 1 0.7 1, ... + 1 1 1, 1 1 1.5, 2 2.5 3, 5 8 inf ]; +up2 = [ 5, 5 5 3, 3 3 2, 2 2 2, 1.5 1.5 1.5, 1.5 1.5 1.5, 1.5 1.5 1.5, ... + 1.5 1 1.5, 2 2 2.5, 2.5 3 3.5, 4.5 5 5, 5 5 5 ]; +low2 = [ inf, inf inf 3, 3 3 2, 2 2 2, 1.5 1.5 1.5, 1.5 1.5 1.5, ... + 1.5 1.5 1.5, 1.5 1 1.5, 2,2 2.5, 2.5 3 3.5, 4.5 5 inf, inf inf inf ]; +clf; +semilogx(W/2/pi,20*log10(abs(H)),'-',fref,Cgoal+up1,'--',fref,Cgoal+up2,':'); +hold on +semilogx(W/2/pi,20*log10(abs(H)),'-',fref,Cgoal-low1,'--',fref,Cgoal-low2,':'); +hold off +xlabel('Frequency [Hz]'); ylabel('Gain [dB]'); +title(['C-weighting, Fs = ',int2str(Fs),' Hz']); +axis([fref(1) max(fref(34),Fs/2) -20 5]); +legend('Filter','Class 1','Class 2',0); + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/filtbank.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/filtbank.m new file mode 100644 index 0000000000000000000000000000000000000000..0f2c9fd2ce048648d4db6fcccd64c16946f35251 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/filtbank.m @@ -0,0 +1,144 @@ +function [p,f] = filtbank(x,Fs,T,arg4); +% FILTBANK One-third-octave band frequency analyser. +% [P,F] = FILTBANK(X,Fs) computes the one-third-octave spectrum +% of X, assuming sampling frequency Fs (in Hz). P is a row vector +% containing RMS powers computed for each 1/3-octave band and expressed +% in dB with 1 as reference level. F contains the corresponding preferred +% labeling frequencies (standard ANSI S1.6-1984). +% +% Plots can be obtained, e.g., with BANKDISP. +% Example: (spectrum of white noise) +% X = rand(1,100000); +% [P,F] = filtbank(X,44100); +% bankdisp(P,F,-40,-20); +% +% The frequency range covered is the standard 'restricted' audio range: +% from 100 Hz to 5000 Hz. +% +% [P,F] = FILTBANK(X,Fs,T) computes a sequence of one-third-octave +% spectra with integration time T (in s). P is a matrix of size +% (LENGTH(X)/(T*Fs)) x LENGTH(F). If T = [] (default), the integration +% time is equal to the length of X. +% +% [P,F] = FILTBANK(X,Fs,T,'extended') covers the 'extended' audio range: +% from 25 Hz to 20 000 Hz. Note that depending on the value of Fs +% the frequency range might be automatically reduced. Warnings will be +% issued if this is the case. +% +% See also BANKDISP, LEQ. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 26, 1997, 3:30pm. + +% References: +% [1] ANSI S1.1-1986 (ASA 65-1986): Specifications for +% Octave-Band and Fractional-Octave-Band Analog and +% Digital Filters, Acoustical Society of America, NY, 1993. +% [2] S. J. Orfanidis, Introduction to Signal Processing, +% Prentice Hall, Englewood Cliffs, 1996. + +if (nargin < 2) | (nargin > 4) + error('Invalid number of arguments'); +end + +pi = 3.14159265358979; +Fref = [ 25 31.5 40, 50 63 80, 100 125 160, 200 250 315, 400 500 630, ... + 800 1000 1250, 1600 2000 2500, 3150 4000 5000, 6300 8000 10000, ... + 12500 16000 20000 ]; % Preferred labeling freq. +Fc = 1000*((2^(1/3)).^[-16:1:13]); % Exact center freq. +N = 3; % Order of analysis filters. +extended = 0; +U = 2^(1/3); + +% Integration time. +if (nargin>=3) + if isempty(T) + T = length(x); + P = zeros(1,length(Fref)); + else % Convert T to number of samples. + T = floor(Fs*T); + P = zeros(floor(length(x)/T),length(Fref)); + end +else + T = length(x); + P = zeros(1,length(Fref)); +end + +if (nargin >= 4) + if strcmp(lower(arg4),'extended') % Extended (25 Hz to 20000 Hz) + extended = 1; + end +end + +% Frequency range. +if (extended) % extended (25 Hz to 20 000 Hz). + i_up = 30; + i_low = 1; +else % restricted (100 Hz to 5000 Hz). + i_up = 24; + i_low = 7; +end + +% Check sampling frequencies and issue warnings. +if (Fs/2) < Fref(i_low)*1.5 + error('Sampling frequency Fs too low.'); +elseif (Fs/2) < Fref(i_up)*1.5 + disp('Warning: frequency range must be reduced (Fs too low).'); + i_up = max(find(Fc<=Fs/3)); +end +% Compute 'pivot' frequency for multirate filter implementation +% All filters below Fs/20 will be implemented after a decimation. +if (Fc(i_low) > Fs/20) + i_dec = 0; +else + i_dec = max(find(Fc<=Fs/20)); +end + +% Design filters and compute RMS powers in 1/3-oct. bands. +% Higher frequencies, direct implementation of filters. +for i = i_up:-1:i_dec+1 + [B,A] = oct3dsgn(Fc(i),Fs,N); + y = filter(B,A,x); + P(:,i) = leq(y,T); +end +% Lower frequencies, decimation by series of 3 bands. +if (i_dec > 0) + [Bu,Au] = oct3dsgn(Fc(i_dec),Fs/2,N); % Upper 1/3-oct. band in last octave. + [Bc,Ac] = oct3dsgn(Fc(i_dec)/U,Fs/2,N); % Center 1/3-oct. band in last octave. + [Bl,Al] = oct3dsgn(Fc(i_dec)/(U^2),Fs/2,N); % Lower 1/3-oct. band in last octave. + i = i_dec; + while i >= i_low+2 + x = decimate(x,2); + T = T/2; + y = filter(Bu,Au,x); + P(:,i) = leq(y,T); + y = filter(Bc,Ac,x); + P(:,i-1) = leq(y,T); + y = filter(Bl,Al,x); + P(:,i-2) = leq(y,T); + i = i-3; + end + if (i == (i_low+1)) + x = decimate(x,2); + T = T/2; + y = filter(Bu,Au,x); + P(:,i) = leq(y,T); + y = filter(Bc,Ac,x); + P(:,i-1) = leq(y,T); + elseif (i == (i_low)) + x = decimate(x,2); + T = T/2; + y = filter(Bu,Au,x); + P(:,i) = leq(y,T); + end +end + +f = Fref(i_low:i_up); +p = P(:,i_low:i_up); + + + + + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/leq.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/leq.m new file mode 100644 index 0000000000000000000000000000000000000000..2d740b6806b1bfb8545b4aaa5f667b42e7e57503 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/leq.m @@ -0,0 +1,29 @@ +function p=leq(x,t,Pref) +% LEQ Computes the sequence of short-time RMS powers (Leq) of a signal. +% P = LEQ(X,T) is a length LENGTH(X)/T column vector whose +% elements are the RMS powers (Leq's) of length T frames of X. +% The powers are expressed in dB with 1 as reference level. +% LEQ(X,T,REF) uses REF as the reference level for the dB +% scale. If a RMS power is equal to zero, a NaN is returned +% for its dB value. +% + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 24, 1997, 4:00pm. + +m = floor(length(x)/t); +p = zeros(m,1); +for i = 1:m + p(i) = sum(x((i-1)*t+1:i*t).^2)/t; +end +idx = (p>0); +if (nargin < 3) + Pref = 1; +end +if ~isempty(idx) + p(idx) = 10*log10(p(idx)/Pref); + p(~idx) = NaN*ones(sum(~idx),1); +else + p = NaN*ones(m,1); +end diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3bank.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3bank.m new file mode 100644 index 0000000000000000000000000000000000000000..9e0d2711a83b55e630cdb9f34dd0dcbf73138d72 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3bank.m @@ -0,0 +1,84 @@ +function [p,f] = oct3bank(x); +% OCT3BANK Simple one-third-octave filter bank. +% OCT3BANK(X) plots one-third-octave power spectra of signal vector X. +% Implementation based on ANSI S1.11-1986 Order-3 filters. +% Sampling frequency Fs = 44100 Hz. Restricted one-third-octave-band +% range (from 100 Hz to 5000 Hz). RMS power is computed in each band +% and expressed in dB with 1 as reference level. +% +% [P,F] = OCT3BANK(X) returns two length-18 row-vectors with +% the RMS power (in dB) in P and the corresponding preferred labeling +% frequencies (ANSI S1.6-1984) in F. +% +% See also OCT3DSGN, OCT3SPEC, OCTDSGN, OCTSPEC. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 23, 1997, 10:30pm. + +% References: +% [1] ANSI S1.1-1986 (ASA 65-1986): Specifications for +% Octave-Band and Fractional-Octave-Band Analog and +% Digital Filters, 1993. +% [2] S. J. Orfanidis, Introduction to Signal Processing, +% Prentice Hall, Englewood Cliffs, 1996. + + +pi = 3.14159265358979; +Fs = 44100; % Sampling Frequency +N = 3; % Order of analysis filters. +F = [ 100 125 160, 200 250 315, 400 500 630, 800 1000 1250, ... + 1600 2000 2500, 3150 4000 5000 ]; % Preferred labeling freq. +ff = (1000).*((2^(1/3)).^[-10:7]); % Exact center freq. +P = zeros(1,18); +m = length(x); + +% Design filters and compute RMS powers in 1/3-oct. bands +% 5000 Hz band to 1600 Hz band, direct implementation of filters. +for i = 18:-1:13 + [B,A] = oct3dsgn(ff(i),Fs,N); + y = filter(B,A,x); + P(i) = sum(y.^2)/m; +end +% 1250 Hz to 100 Hz, multirate filter implementation (see [2]). +[Bu,Au] = oct3dsgn(ff(15),Fs,N); % Upper 1/3-oct. band in last octave. +[Bc,Ac] = oct3dsgn(ff(14),Fs,N); % Center 1/3-oct. band in last octave. +[Bl,Al] = oct3dsgn(ff(13),Fs,N); % Lower 1/3-oct. band in last octave. +for j = 3:-1:0 + x = decimate(x,2); + m = length(x); + y = filter(Bu,Au,x); + P(j*3+3) = sum(y.^2)/m; + y = filter(Bc,Ac,x); + P(j*3+2) = sum(y.^2)/m; + y = filter(Bl,Al,x); + P(j*3+1) = sum(y.^2)/m; +end + +% Convert to decibels. +Pref = 1; % Reference level for dB scale. +idx = (P>0); +P(idx) = 10*log10(P(idx)/Pref); +P(~idx) = NaN*ones(sum(~idx),1); + +% Generate the plot +if (nargout == 0) + bar(P); + ax = axis; + axis([0 19 ax(3) ax(4)]) + set(gca,'XTick',[2:3:18]); % Label frequency axis on octaves. + set(gca,'XTickLabels',F(2:3:length(F))); % MATLAB 4.1c +% set(gca,'XTickLabel',F(2:3:length(F))); % MATLAB 5.1 + xlabel('Frequency band [Hz]'); ylabel('Power [dB]'); + title('One-third-octave spectrum') +% Set up output parameters +elseif (nargout == 1) + p = P; +elseif (nargout == 2) + p = P; + f = F; +end + + + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3dsgn.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3dsgn.m new file mode 100644 index 0000000000000000000000000000000000000000..6340775d49daa6ab0a7e874e31e2022a2420d2ca --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3dsgn.m @@ -0,0 +1,45 @@ +function [B,A] = oct3dsgn(Fc,Fs,N); +% OCT3DSGN Design of a one-third-octave filter. +% [B,A] = OCT3DSGN(Fc,Fs,N) designs a digital 1/3-octave filter with +% center frequency Fc for sampling frequency Fs. +% The filter is designed according to the Order-N specification +% of the ANSI S1.1-1986 standard. Default value for N is 3. +% Warning: for meaningful design results, center frequency used +% should preferably be in range Fs/200 < Fc < Fs/5. +% Usage of the filter: Y = FILTER(B,A,X). +% +% Requires the Signal Processing Toolbox. +% +% See also OCT3SPEC, OCTDSGN, OCTSPEC. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 25, 1997, 2:00pm. + +% References: +% [1] ANSI S1.1-1986 (ASA 65-1986): Specifications for +% Octave-Band and Fractional-Octave-Band Analog and +% Digital Filters, 1993. + +if (nargin > 3) | (nargin < 2) + error('Invalide number of arguments.'); +end +if (nargin == 2) + N = 3; +end +if (Fc > 0.88*(Fs/2)) + error('Design not possible. Check frequencies.'); +end + +% Design Butterworth 2Nth-order one-third-octave filter +% Note: BUTTER is based on a bilinear transformation, as suggested in [1]. +pi = 3.14159265358979; +f1 = Fc/(2^(1/6)); +f2 = Fc*(2^(1/6)); +Qr = Fc/(f2-f1); +Qd = (pi/2/N)/(sin(pi/2/N))*Qr; +alpha = (1 + sqrt(1+4*Qd^2))/2/Qd; +W1 = Fc/(Fs/2)/alpha; +W2 = Fc/(Fs/2)*alpha; +[B,A] = butter(N,[W1,W2]); + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3spec.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3spec.m new file mode 100644 index 0000000000000000000000000000000000000000..89197896c9887f4e50534c56837e18308cb13a41 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/oct3spec.m @@ -0,0 +1,115 @@ +function [g,f] = oct3spec(B,A,Fs,Fc,s,n); +% OCT3SPEC Plots a one-third-octave filter characteristics. +% OCT3SPEC(B,A,Fs,Fc) plots the attenuation of the filter defined by +% B and A at sampling frequency Fs. Fc is the center frequency of +% the one-third-octave filter. The plot covers one decade on both sides +% of Fc. +% +% OCT3SPEC(B,A,Fs,Fc,'ANSI',N) superposes the ANSI Order-N analog +% specification for comparison. Default is N = 3. +% +% OCT3SPEC(B,A,Fs,Fc,'IEC',N) superposes the characteristics of the +% IEC 61260 class N specification for comparison. Default is N = 1. +% +% [G,F] = OCT3SPEC(B,A,Fs,Fc) returns two 512-point vectors with +% the gain (in dB) in G and logarithmically spaced frequencies in F. +% The plot can then be obtained by SEMILOGX(F,G) +% +% See also OCT3DSGN, OCTSPEC, OCTDSGN. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Sept. 4, 1997, 11:00am. + +% References: +% [1] ANSI S1.1-1986 (ASA 65-1986): Specifications for +% Octave-Band and Fractional-Octave-Band Analog and +% Digital Filters, 1993. +% [2] IEC 61260 (1995-08): Electroacoustics -- Octave-Band and +% Fractional-Octave-Band Filters, 1995. + +if (nargin < 4) | (nargin > 6) + error('Invalide number of input arguments.'); +end + +ansi = 0; +iec = 0; +if nargin > 4 + if strcmp(lower(s),'ansi') + ansi = 1; + if nargin == 5 + n = 3; + end + elseif strcmp(lower(s),'cei') | strcmp(lower(s),'iec') + iec = 1; + if nargin == 5 + n = 1 + end + if (n < 0) | (n > 3) + error('IEC class must be 0, 1, or 2'); + end + end +end + +N = 512; +pi = 3.14159265358979; +F = logspace(log10(Fc/10),log10(min(Fc*10,Fs/2)),N); +H = freqz(B,A,2*pi*F/Fs); +G = 20*log10(abs(H)); + +% Set output variables +if nargout ~= 0 + g = G; f = F; + return +end + +% Generate the plot +if (ansi) % ANSI Order-n specification + f = logspace(log10(Fc/10),log10(Fc*10),N); + f1 = Fc/(2^(1/6)); + f2 = Fc*(2^(1/6)); + Qr = Fc/(f2-f1); + Qd = (pi/2/n)/(sin(pi/2/n))*Qr; + Af = 10*log10(1+Qd^(2*n)*((f/Fc)-(Fc./f)).^(2*n)); + semilogx(F,G,f,-Af,'--'); + legend('Filter',['ANSI order-' int2str(n)],0); +elseif (iec) % CEI specification + semilogx(F,G); + hold on + if n == 0 + tolup = [ .15 .15 .15 .15 .15 -2.3 -18.0 -42.5 -62 -75 -75 ]; + tollow = [ -.15 -.2 -.4 -1.1 -4.5 -realmax -inf -inf -inf -inf -inf ]; + elseif n == 1 + tolup = [ .3 .3 .3 .3 .3 -2 -17.5 -42 -61 -70 -70 ]; + tollow = [ -.3 -.4 -.6 -1.3 -5 -realmax -inf -inf -inf -inf -inf ]; + elseif n == 2 + tolup = [ .5 .5 .5 .5 .5 -1.6 -16.5 -41 -55 -60 -60 ]; + tollow = [ -.5 -.6 -.8 -1.6 -5.5 -realmax -inf -inf -inf -inf -inf ]; + end + % Reference frequencies in base 2 system + f = Fc * [1 1.02676 1.05594 1.08776 1.12246 1.12246 1.29565 1.88695 ... + 3.06955 5.43474 NaN ]; + f(length(f)) = realmax; + ff = Fc * [1 0.97394 0.94702 0.91932 0.89090 0.89090 0.77181 0.52996 ... + 0.32578 0.18400 NaN ]; + ff(length(ff)) = realmin; + semilogx(F,G,f,tolup,'--'); + semilogx(F,G,f,tollow,'--'); + semilogx(F,G,ff,tolup,'--'); + semilogx(F,G,ff,tollow,'--'); + hold off + legend('Filter',['IEC class ' int2str(n)],0); +else + semilogx(F,G); +end +xlabel('Frequency [Hz]'); ylabel('Gain [dB]'); +title(['One-third-octave filter: Fc =',int2str(Fc),' Hz, Fs = ',int2str(Fs),' Hz']); +axis([Fc/10 Fc*10 -80 5]); +grid on + + + + + + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/octdsgn.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/octdsgn.m new file mode 100644 index 0000000000000000000000000000000000000000..5e7fa6990f875055211aba77e8bfab3eb4067f24 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/octdsgn.m @@ -0,0 +1,55 @@ +function [B,A] = octdsgn(Fc,Fs,N); +% OCTDSGN Design of an octave filter. +% [B,A] = OCTDSGN(Fc,Fs,N) designs a digital octave filter with +% center frequency Fc for sampling frequency Fs. +% The filter are designed according to the Order-N specification +% of the ANSI S1.1-1986 standard. Default value for N is 3. +% Warning: for meaningful design results, center values used +% should preferably be in range Fs/200 < Fc < Fs/5. +% Usage of the filter: Y = FILTER(B,A,X). +% +% Requires the Signal Processing Toolbox. +% +% See also OCTSPEC, OCT3DSGN, OCT3SPEC. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Aug. 22, 1997, 9:00pm. + +% References: +% [1] ANSI S1.1-1986 (ASA 65-1986): Specifications for +% Octave-Band and Fractional-Octave-Band Analog and +% Digital Filters, 1993. + +if (nargin > 3) | (nargin < 2) + error('Invalide number of arguments.'); +end +if (nargin == 2) + N = 3; +end +if (Fc > 0.70*(Fs/2)) + error('Design not possible. Check frequencies.'); +end + +% Design Butterworth 2Nth-order octave filter +% Note: BUTTER is based on a bilinear transformation, as suggested in [1]. +%W1 = Fc/(Fs/2)*sqrt(1/2); +%W2 = Fc/(Fs/2)*sqrt(2); +pi = 3.14159265358979; +beta = pi/2/N/sin(pi/2/N); +alpha = (1+sqrt(1+8*beta^2))/4/beta; +W1 = Fc/(Fs/2)*sqrt(1/2)/alpha; +W2 = Fc/(Fs/2)*sqrt(2)*alpha; +[B,A] = butter(N,[W1,W2]); + + + + + + + + + + + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/octspec.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/octspec.m new file mode 100644 index 0000000000000000000000000000000000000000..e9148973cea8c9ccc6b4532282fb73add3b42154 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/octave/octspec.m @@ -0,0 +1,115 @@ +function [g,f] = octspec(B,A,Fs,Fc,s,n); +% OCTSPEC Plots an octave filter characteristics. +% OCTSPEC(B,A,Fs,Fc) plots the attenuation of the filter defined by +% B and A at sampling frequency Fs. Fc is the center frequency of +% the octave filter. The plot covers one decade on both sides of Fc. +% +% OCTSPEC(B,A,Fs,Fc,'ANSI',N) superposes the ANSI Order-N analog +% specification for comparison. Default is N = 3. +% +% OCTSPEC(B,A,Fs,Fc,'IEC',N) superposes the characteristics of the +% IEC 61260 class N specification for comparison. Default is N = 1. +% +% [G,F] = OCTSPEC(B,A,Fs,Fc) returns two 512-point vectors with +% the gain (in dB) in G and logarithmically spaced frequencies in F. +% The plot can then be obtained by SEMILOGX(F,G) +% +% See also OCTDSGN, OCT3SPEC, OCT3DSGN. + +% Author: Christophe Couvreur, Faculte Polytechnique de Mons (Belgium) +% couvreur@thor.fpms.ac.be +% Last modification: Sept. 4, 1997, 10:30am. + +% References: +% [1] ANSI S1.1-1986 (ASA 65-1986): Specifications for +% Octave-Band and Fractional-Octave-Band Analog and +% Digital Filters, 1993. +% [2] IEC 61260 (1995-08): Electroacoustics -- Octave-Band and +% Fractional-Octave-Band Filters, 1995. + +if (nargin < 4) | (nargin > 6) + error('Invalid number of input arguments.'); +end + +ansi = 0; +iec = 0; +if nargin > 4 + if strcmp(lower(s),'ansi') + ansi = 1; + if nargin == 5 + n = 3; + end + elseif strcmp(lower(s),'cei') | strcmp(lower(s),'iec') + iec = 1; + if nargin == 5 + n = 1 + end + if (n < 0) | (n > 3) + error('IEC class must be 0, 1, or 2'); + end + end +end + +N = 512; +pi = 3.14159265358979; +F = logspace(log10(Fc/10),log10(min(Fc*10,Fs/2)),N); +H = freqz(B,A,2*pi*F/Fs); +G = 20*log10(abs(H)); + +% Set output variables. +if nargout ~= 0 + g = G; f = F; + return +end + +% Generate the plot +if (ansi) % ANSI Order-n specification + f = logspace(log10(Fc/10),log10(Fc*10),N); + f1 = Fc/sqrt(2); + f2 = Fc*sqrt(2); + Qr = Fc/(f2-f1); + Qd = (pi/2/n)/(sin(pi/2/n))*Qr; + Af = 10*log10(1+Qd^(2*n)*((f/Fc)-(Fc./f)).^(2*n)); + semilogx(F,G,f,-Af,'--'); + legend('Filter',['ANSI order-' int2str(n)],0); +elseif (iec) % CEI specification + semilogx(F,G); + hold on + if n == 0 + tolup = [ .15 .15 .15 .15 .15 -2.3 -18.0 -42.5 -62 -75 -75 ]; + tollow = [ -.15 -.2 -.4 -1.1 -4.5 -realmax -inf -inf -inf -inf -inf ]; + elseif n == 1 + tolup = [ .3 .3 .3 .3 .3 -2 -17.5 -42 -61 -70 -70 ]; + tollow = [ -.3 -.4 -.6 -1.3 -5 -realmax -inf -inf -inf -inf -inf ]; + elseif n == 2 + tolup = [ .5 .5 .5 .5 .5 -1.6 -16.5 -41 -55 -60 -60 ]; + tollow = [ -.5 -.6 -.8 -1.6 -5.5 -realmax -inf -inf -inf -inf -inf ]; + end + U = 2; + f = Fc * U.^[ 0 1/8 1/4 3/8 1/2 1/2 1 2 3 4 NaN ]; + ff = Fc * U.^[ 0 -1/8 -1/4 -3/8 -1/2 -1/2 -1 -2 -3 -4 NaN ]; + f(length(f)) = realmax; + ff(length(ff)) = realmin; + semilogx(F,G,f,tolup,'--'); + semilogx(F,G,f,tollow,'--'); + semilogx(F,G,ff,tolup,'--'); + semilogx(F,G,ff,tollow,'--'); + hold off + legend('Filter',['IEC class ' int2str(n)],0); +else + semilogx(F,G); +end +xlabel('Frequency [Hz]'); ylabel('Gain [dB]'); +title(['Octave filter: Fc =',int2str(Fc),' Hz, Fs = ',int2str(Fs),' Hz']); +axis([Fc/10 Fc*10 -80 5]); +grid on + + + + + + + + + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/plotting_rir_compare.m b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/plotting_rir_compare.m new file mode 100644 index 0000000000000000000000000000000000000000..a5d170a0991fbb8c3dbd1fc68f07a036e69c0f46 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/plotting_rir_compare.m @@ -0,0 +1,226 @@ +addpath RIRs + +[kit, fs] = audioread('Kitchen_BFormat.wav'); + +L = length(kit); +t = (1:L)/fs; + +initial_delay = find(abs(kit(:,1))==max(abs(kit(:,1)))); +Delay_kt = initial_delay; +Delay_rsao = 303; % For Kitchen in RSAO json file + +t2 = t(1:0.2*fs-Delay_kt+1); +t1 = t(1:0.2*fs-Delay_rsao+1); + + +%load rir_regen_rsao.mat +addpath Unity-ogg-files\ + +[sirr_rir,fs]=audioread('SIRR_Kitchen_RIR.ogg'); +rir_sirr_fig_mid = sirr_rir(Delay_kt:0.2*fs,:); +% Re-ordering the channels from Unity to WXYZ +rir_sirr_fig(:,1)=rir_sirr_fig_mid(:,1); % channel W +rir_sirr_fig(:,2)=rir_sirr_fig_mid(:,4); % channel X +rir_sirr_fig(:,3)=rir_sirr_fig_mid(:,2); % channel Y +rir_sirr_fig(:,4)=rir_sirr_fig_mid(:,3); % channel Z + +% [rsao_rir,fs]=audioread('RSAO_Kitchen_rir_64.ogg'); +[rsao_rir,fs]=audioread('RSAO_Kitchen_SigTmix.ogg'); +rir_regen_rsao_mid=rsao_rir; %(1:10*fs,:); +% Re-ordering the channels from Unity to WXYZ +rir_regen_rsao(:,1)=rir_regen_rsao_mid(:,1); % channel W +rir_regen_rsao(:,2)=rir_regen_rsao_mid(:,4); % channel X +rir_regen_rsao(:,3)=rir_regen_rsao_mid(:,2); % channel Y +rir_regen_rsao(:,4)=rir_regen_rsao_mid(:,3); % channel Z + +%[merged_rir,fs]=audioread('T_diff_Combo_Kitchen_rir.ogg'); +%[merged_rir,fs]=audioread('Combined_Kitchen_Han.ogg'); +%[merged_rir,fs]=audioread('Combined_Kitchen_Han_Tm.ogg'); +[merged_rir,fs]=audioread('Combined_Kitchen_nondiff_Tdiff_Han.ogg'); + +merged_rir(1,:) = rir_sirr_fig_mid (1,:); +merged_rir_fig_mid = merged_rir(1:0.2*fs,:); +% Re-ordering the channels from Unity to WXYZ +merged_rir_fig(:,1)=merged_rir_fig_mid(:,1); % channel W +merged_rir_fig(:,2)=merged_rir_fig_mid(:,4); % channel X +merged_rir_fig(:,3)=merged_rir_fig_mid(:,2); % channel Y +merged_rir_fig(:,4)=merged_rir_fig_mid(:,3); % channel Z + +%% +ch = 1; +figure; +subplot(3,1,1); +plot(t2', kit(Delay_kt:0.2*fs,ch)); hold on; +plot(t2',rir_sirr_fig(1:0.2*fs-Delay_kt+1,ch),'r'); +ylim([-0.4 0.4]); +xlim([0 0.15]); % xlabel ({'Time [s]'},'FontSize',10); +ylabel({'Amplitude'},'FontSize',12); +title('(a)','FontSize',12); +legend({'GT RIR','SIRR'},'FontSize',10) + +figure; +subplot(2,1,1); + +plot(t1', kit(Delay_rsao:0.2*fs,ch)); hold on; +% plot(t1',rir_regen_rsao(1:0.2*fs-Delay_rsao+1,ch),'r'); ylim([-0.4 0.4]); +% I realized that the direct sound at the beginning was not recorded in Unity +% Therefore, I consider the second impulse +plot(t1',rir_regen_rsao(L+1:L+0.2*fs-Delay_rsao+1,ch),'r'); ylim([-0.4 0.4]); +xlim([0 0.15]); % xlabel ({'Time [s]'},'FontSize',10); +ylabel({'Amplitude'},'FontSize',12); +title('(b)','FontSize',12); +legend({'GT RIR','RSAO'},'FontSize',10) + +T_difuse = 0.04*fs; +% T_mix = round(0.0277*fs); +%initial_delay = 303; +T_mix = T_difuse - initial_delay; + +%figure; +subplot(2,1,2); +% plot(t1', kit(Delay_rsao:0.2*fs,ch)); hold on; +% plot(t1',merged_rir_fig(1:0.2*fs-Delay_rsao+1,ch),'r'); +plot(t2', kit(Delay_kt:0.2*fs,ch)); hold on; +plot(t2',merged_rir_fig(1:0.2*fs-Delay_kt+1,ch),'r'); +% plot(t2(1:T_mix-1)',merged_rir_fig(1:T_mix-1,ch),'r'); +% hold on; plot(t1(T_mix:end)',rir_regen_rsao(T_mix:0.2*fs-Delay_rsao+1,ch),'r'); +ylim([-0.4 0.4]); +xlim([0 0.15]); xlabel ({'Time [s]'},'FontSize',12); +ylabel({'Amplitude'},'FontSize',12); +title('(c)','FontSize',12); +legend({'GT RIR','Combined'},'FontSize',10) + +%% +ch = 1; +M = 1000; +figure; +subplot(3,1,1); +plot(t2', 10*log10(abs(kit(Delay_kt:0.2*fs,ch)))); hold on; +plot(t2', 10*log10(abs(rir_sirr_fig(1:0.2*fs-Delay_kt+1,ch))),'r'); +ylim([-30 2]); +xlim([0 0.02]); % xlabel ({'Time [s]'},'FontSize',10); +ylabel({'Amplitude'},'FontSize',12); +title('(a)','FontSize',12); +legend({'GT RIR','SIRR'},'FontSize',10) + +figure; +subplot(2,1,1); +rir_regen_rsao(1,:) = rir_regen_rsao(L+1,:); +plot(M*t1', 10*log10(abs(kit(Delay_rsao:0.2*fs,ch)))); hold on; +plot(M*t1',10*log10(abs(rir_regen_rsao(L+1:L+0.2*fs-Delay_rsao+1,ch))),'r'); ylim([-40 2]); +% I realized that the direct sound at the beginning was not recorded in Unity +% Therefore, I consider the second impulse +% plot(t1',rir_regen_rsao(L+1:L+0.2*fs-Delay_rsao+1,ch),'r'); ylim([-0.4 0.4]); +xlim([0 10]); % xlabel ({'Time [s]'},'FontSize',10); +ylabel({'Amp[dB]'},'FontSize',12); +title('(a)','FontSize',12); +legend({'GT RIR','RSAO'},'FontSize',10); grid on; + +% T_difuse = 0.04*fs; +% T_mix = round(0.0277*fs); +%initial_delay = 303; +% T_mix = T_difuse - initial_delay; + +%figure; +subplot(2,1,2); +% plot(t1', kit(Delay_rsao:0.2*fs,ch)); hold on; +% plot(t1',merged_rir_fig(1:0.2*fs-Delay_rsao+1,ch),'r'); +plot(M*t2', 10*log10(abs(kit(Delay_kt:0.2*fs,ch)))); hold on; +plot(M*t2', 10*log10(abs(merged_rir_fig(1:0.2*fs-Delay_kt+1,ch))),'r'); +% plot(t2(1:T_mix-1)',merged_rir_fig(1:T_mix-1,ch),'r'); +% hold on; plot(t1(T_mix:end)',rir_regen_rsao(T_mix:0.2*fs-Delay_rsao+1,ch),'r'); +ylim([-40 2]); +xlim([0 10]); xlabel ({'Time [ms]'},'FontSize',12); +ylabel({'Amp[dB]'},'FontSize',12); +title('(b)','FontSize',12); +legend({'GT RIR','Combined'},'FontSize',10); grid on; +%% ........................................................................ + +addpath 'RIRs' 'IoSR Toolbox' 'octave' + +earlyt = 0.04; % for kitchen +% tlen = 0.2968; % for kitchen in order to not exceed the RSAO second impulse +tlen = 0.3; % Kitchen +% earlyt = 0.03; % for DWRC +% tlen = 0.20; % for DWRC +% earlyt = 0.08; % for CY +% tlen = 0.5; % for CY + +rir_record = kit(Delay_kt:tlen*fs,:); +kit_corr = zeros(1,4); +rir_record(:,1)=rir_record(:,1)./max(rir_record(:,1)); +for i=1:4 % Number of channels + xcor_kit =xcorr(rir_record(1:earlyt*fs,i),rir_record(1:earlyt*fs,i)); + kit_corr(i)=max(xcor_kit); +end +clear i +audiowrite('rir_record.wav',rir_record./2,fs); +[RT, DRR, C50, Cfs, EDT] = iosr.acoustics.irStats('rir_record.wav','graph', true, 'spec', 'full'); + +% [RT, DRR, C50, Cfs, EDT] = iosr.acoustics.irStats('Kitchen_Bformat.wav'); + +rir_sirr_mid = sirr_rir(Delay_kt:tlen*fs,:); +% Re-ordering the channels from Unity to WXYZ +rir_sirr(:,1)=rir_sirr_mid(:,1)./(max(rir_sirr_mid(:,1))); % channel W +rir_sirr(:,2)=rir_sirr_mid(:,4); % channel X +rir_sirr(:,3)=rir_sirr_mid(:,2); % channel Y +rir_sirr(:,4)=rir_sirr_mid(:,3); % channel Z + +audiowrite('rir_sirr.wav',rir_sirr./2,fs); +sirr_corr = zeros(1,4); +for i=1:4 % Number of channels + xcor_sirr =xcorr(rir_record(1:earlyt*fs,i),rir_sirr(1:earlyt*fs,i)); + sirr_corr(i)=max(xcor_sirr); +end +clear i + +[RT_sirr, DRR_sirr, C50_sirr, Cfs, EDT_sirr] = iosr.acoustics.irStats('rir_sirr.wav','graph', true, 'spec', 'full'); + + +rsao_rir(1,:) = rsao_rir(L+1,:); +rir_rsao_mid = rsao_rir(1:tlen*fs-Delay_kt+1,:); % To have the same length +% rir_rsao_mid = rsao_rir(L+1:L+tlen*fs-Delay_kt+1,:); % To have the same length +% as SIRR RIR +% Re-ordering the channels from Unity to WXYZ +rir_rsao(:,1)=rir_rsao_mid(:,1)./(max(rir_rsao_mid(:,1))); % channel W +rir_rsao(:,2)=rir_rsao_mid(:,4); % channel X +rir_rsao(:,3)=rir_rsao_mid(:,2); % channel Y +rir_rsao(:,4)=rir_rsao_mid(:,3); % channel Z +audiowrite('rir_rsao.wav',rir_rsao./2,fs); + +rsao_corr = zeros(1,4); +for i=1:4 % Number of channels + xcor_rsao =xcorr(rir_record(1:earlyt*fs,i),rir_rsao(1:earlyt*fs,i)); + rsao_corr(i)=max(xcor_rsao); +end +clear i + +[RT_rsao, DRR_rsao, C50_rsao, Cfs, EDT_rsao] = ... + iosr.acoustics.irStats('rir_rsao.wav','graph', true, 'spec', 'full'); + +merged_rir(1,:) = sirr_rir(Delay_kt,:); +rir_merged_mid = merged_rir(1:tlen*fs-Delay_kt,:); +% Re-ordering the channels from Unity to WXYZ +rir_merged(:,1)=rir_merged_mid(:,1)./(max(rir_merged_mid(:,1))); % channel W +rir_merged(:,2)=rir_merged_mid(:,4); % channel X +rir_merged(:,3)=rir_merged_mid(:,2); % channel Y +rir_merged(:,4)=rir_merged_mid(:,3); % channel Z +audiowrite('rir_merged.wav',rir_merged./2,fs); + +merged_corr = zeros(1,4); +for i=1:4 % Number of channels + xcor_merged =xcorr(rir_record(1:1:earlyt*fs,i),rir_merged(1:earlyt*fs,i)); + merged_corr(i)=max(xcor_merged); +end +clear i + +[RT_merged, DRR_merged, C50_merged, Cfs, EDT_merged] = ... + iosr.acoustics.irStats('rir_merged.wav','graph', true, 'spec', 'full'); + + +results = [mean(RT); C50; mean(EDT) + mean(RT_sirr); C50_sirr; mean(EDT_sirr) + mean(RT_rsao); C50_rsao; mean(EDT_rsao) + mean(RT_merged); C50_merged; mean(EDT_merged)]; + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/RIR_MR_Unity_bf.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/RIR_MR_Unity_bf.wav new file mode 100644 index 0000000000000000000000000000000000000000..402b0341bb1f5972e89ea4005bf99018f53ce7f3 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/RIR_MR_Unity_bf.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/inverse_filter_16bit.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/inverse_filter_16bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..01f1456817b5eba8cbe616c6330c5bcf9e7ab537 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/inverse_filter_16bit.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/sine_sweep_16bit.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/sine_sweep_16bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..54c0d175c64672b7f2a0cc817419446d1d9ba4a1 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR-evaluation-Matlab/sounds/MR_MDBNet/sine_sweep_16bit.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/Camparision Graphs-checkpoint.ipynb b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/Camparision Graphs-checkpoint.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..6cf7dc56fd78fd020c0588b3f6e89ebf0454f63a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/Camparision Graphs-checkpoint.ipynb @@ -0,0 +1,250 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "d788205d-9fc6-4871-9c8e-ca10245bb5d3", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "e2850bdc-3dde-474a-b4c8-b637c32fe32c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "################################################### graph without scale the KT and ST ########################################\n", + "##############################################################################################################################\n", + "##############################################################################################################################\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################## EDT with 5% JND threshold #############################################################\n", + "data = {'ours_KT': [0.30],\n", + " 'ours_MR':[0.32],\n", + " 'ours_UL':[0.33],\n", + " #'ours_ST':[ 0.79],\n", + " 'Kim19_KT': [0.86],\n", + " 'Kim19_MR': [0.53],\n", + " 'Kim19_UL': [0.66],\n", + " #'Kim19_ST': [1.55],\n", + " 'Kim21_KT': [0.45],\n", + " 'Kim21_MR':[0.49],\n", + " 'Kim21_UL':[0.51],\n", + " # 'Kim21_ST': [0.96],\n", + " 'GT_KT':[0.41],\n", + " 'GT_MR':[0.21],\n", + " 'GT_UL':[0.20],\n", + " # 'GT_ST':[0.22]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "#GT = [0.41,0.21,0.20, 0.22]\n", + "GT = [0.41,0.21,0.20]\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='D', s= 60 ) \n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='o',s= 60, ax=ax1 ) \n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR',color = 'r',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='o',s= 60, ax=ax1) \n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='s',s= 60, ax=ax1 ) \n", + "\n", + "\n", + "#ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "#ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST',color = 'g' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "#ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='s', s= 60, ax=ax1 ) \n", + "\n", + "\n", + "# Plot the perfect estimation line\n", + "plt.plot([0, 2], [0, 2], linestyle='-', color='black')\n", + "\n", + "# Plot the JND thresholds (5% above and below the perfect estimation line)\n", + "x_vals = [0, 3]\n", + "y_vals_upper = [x * 1.05 for x in x_vals]\n", + "y_vals_lower = [x * 0.95 for x in x_vals]\n", + "plt.plot(x_vals, y_vals_upper, linestyle='--', color='black')\n", + "plt.plot(x_vals, y_vals_lower, linestyle='--', color='black')\n", + "\n", + "# Set the limits of the plot\n", + "plt.xlim(0, 2)\n", + "plt.ylim(0, 0.6)\n", + "# Set x-ticks with 0.5 intervals\n", + "# plt.xticks([0, 0.5, 1.0, 1.5, 2.0])\n", + "\n", + "plt.title ('EDT')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Ours'),\n", + " Line2D([0], [0], marker='', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL'),]\n", + " # Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "\n", + "\n", + "plt.legend(handles=legend_elements, loc='upper right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "903fbeeb-63cf-488d-a816-d9fb3fdba2a5", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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AeD+Ja8DBw7g2rVr8j7KYG1tjaqqKnz55ZfIz8/Hpk2bsH79eoU2lpaWKCsrw969e3Hjxg3cuXMHNjY2eOWVVzBz5kxs27YNly5dwtGjRxEaGoqdO3cCAN5++22kpaUhLCwMeXl5+Oqrrxq8LPaAs7MzDh48KJ++dOkSgoODkZmZiYKCAuzevRt5eXno37+/vM3PP/8MKysr9OnTR0kjQ0RNxSBERA1KS0uDmZmZwucf//gHAMDIyAjffPMNRo0ahSFDhuCnn35CSkqK/H6bTz75BJcvX0afPn2UevnH1tYWq1atwsqVKzFo0CB89913CA0NVWjj6OiIN998E97e3ujRowc+//xzAPcvV82cORMLFixA37594eHhgV9//RXm5uYAgJEjR+Kbb75BZGQkbG1tsXv3bnz44YePrGn27NnYtWsXSktLAQC6uro4d+4cXnzxRdjY2GDOnDmYP38+3njjDXmfH374Af7+/soaFiJqBokQQqi6CCKijsDT0xPPPvssgoODH9k2NzcX48ePx4ULF2BoaNgK1RFRXXhGiIhISb744gvo6+s3qm1hYSH+/e9/MwQRqRjPCBEREVGnxTNCRERE1GkxCBEREVGnxSBEREREnRaDEBEREXVaDEJERETUaTEIERERUafFIERERESdFoMQERERdVoMQkRERNRp/R9aDhorbq+6jAAAAABJRU5ErkJggg==", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "################################################### graph without scale the KT and ST ########################################\n", + "##############################################################################################################################\n", + "##############################################################################################################################\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################################## RT60 with 20% JND threshold ################################################################\n", + "# Data\n", + "data = {'ours_KT': [0.44],\n", + " 'ours_MR':[0.47],\n", + " 'ours_UL':[0.42],\n", + " #'ours_ST':[1.85],\n", + " 'Kim19_KT': [1.76],\n", + " 'Kim19_MR': [0.88],\n", + " 'Kim19_UL': [1.10],\n", + " #'Kim19_ST': [2.13],\n", + " 'Kim21_KT': [0.63],\n", + " 'Kim21_MR':[0.67],\n", + " 'Kim21_UL':[0.77],\n", + " #'Kim21_ST': [1.88],\n", + " 'GT_KT':[0.42],\n", + " 'GT_MR':[0.63],\n", + " 'GT_UL':[0.38],\n", + " #'GT_ST':[1.88]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "#GT = [0.42,0.63,0.38, 1.88]\n", + "GT = [0.42,0.63,0.38]\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT', color='yellow', edgecolors='black', marker='D', s=60)\n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT', color='yellow', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT', color='yellow', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR', color='red', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR', color='red', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR', color='red', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL', color='blue', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL', color='blue', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL', color='blue', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "#ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST', color='green', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "#ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST', color='green', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "#ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST', color='green', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "# Plot the perfect estimation line\n", + "plt.plot([0, 2], [0, 2], linestyle='-', color='black')\n", + "\n", + "# Plot the JND thresholds (20% above and below the perfect estimation line)\n", + "x_vals = [0, 3]\n", + "y_vals_upper = [x * 1.20 for x in x_vals]\n", + "y_vals_lower = [x * 0.80 for x in x_vals]\n", + "plt.plot(x_vals, y_vals_upper, linestyle='--', color='black')\n", + "plt.plot(x_vals, y_vals_lower, linestyle='--', color='black')\n", + "\n", + "# Set the limits of the plot\n", + "plt.xlim(0, 3)\n", + "plt.ylim(0, 2)\n", + "\n", + "# Set y-ticks with 0.5 intervals\n", + "plt.yticks([0, 0.5, 1.0, 1.5, 2.0])\n", + "\n", + "plt.title('RT60')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Ours'),\n", + " Line2D([0], [0], marker='', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL')]\n", + " # Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "plt.legend(handles=legend_elements, loc='right')\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19f04536-fba6-4453-a73b-859e7d095cf9", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (RIR_env)", + "language": "python", + "name": "rir_env" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/Camparision Graphs_RT60_EDTv4-checkpoint.ipynb b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/Camparision Graphs_RT60_EDTv4-checkpoint.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..2f67f0c61dc51cdcc3d076a342cd40a0d97cec72 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/Camparision Graphs_RT60_EDTv4-checkpoint.ipynb @@ -0,0 +1,625 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "d788205d-9fc6-4871-9c8e-ca10245bb5d3", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "0961b884", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#####################################Using model (1) and model (2)###############################################\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################## EDT comparision plot#############################################################\n", + "data = {'ours_KT': [0.62],\n", + " 'ours_MR':[0.44],\n", + " 'ours_UL':[0.51],\n", + " 'ours_ST':[ 1.44],\n", + " 'Kim19_KT': [0.86],\n", + " 'Kim19_MR': [0.53],\n", + " 'Kim19_UL': [0.66],\n", + " 'Kim19_ST': [1.55],\n", + " 'Kim21_KT': [0.45],\n", + " 'Kim21_MR':[0.49],\n", + " 'Kim21_UL':[0.51],\n", + " 'Kim21_ST': [0.96],\n", + " 'GT_KT':[0.41],\n", + " 'GT_MR':[0.21],\n", + " 'GT_UL':[0.20],\n", + " 'GT_ST':[0.22]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "GT = [0.41,0.21,0.20, 0.22]\n", + "\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='D', s= 60 ) \n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='o',s= 60, ax=ax1 ) \n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR',color = 'r',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='o',s= 60, ax=ax1) \n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='s',s= 60, ax=ax1 ) \n", + "\n", + "\n", + "ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST',color = 'g' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='s', s= 60, ax=ax1 ) \n", + "plt.plot(GT, GT, marker='x', linestyle='--', color='black') \n", + "plt.title ('EDT')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Proposed'),\n", + " Line2D([0], [0], marker='x', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL'),\n", + " Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "\n", + "\n", + "plt.legend(handles=legend_elements, loc='upper right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "b60d94a4-d1ee-4595-84b5-48b2c13e1807", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#####################################Using model (1) and model (2)###############################################\n", + "\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################## EDT with 5% JND threshold #############################################################\n", + "data = {'ours_KT': [0.62],\n", + " 'ours_MR':[0.44],\n", + " 'ours_UL':[0.51],\n", + " 'ours_ST':[ 1.44],\n", + " 'Kim19_KT': [0.86],\n", + " 'Kim19_MR': [0.53],\n", + " 'Kim19_UL': [0.66],\n", + " 'Kim19_ST': [1.55],\n", + " 'Kim21_KT': [0.45],\n", + " 'Kim21_MR':[0.49],\n", + " 'Kim21_UL':[0.51],\n", + " 'Kim21_ST': [0.96],\n", + " 'GT_KT':[0.41],\n", + " 'GT_MR':[0.21],\n", + " 'GT_UL':[0.20],\n", + " 'GT_ST':[0.22]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "GT = [0.41,0.21,0.20, 0.22]\n", + "\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='D', s= 60 ) \n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='o',s= 60, ax=ax1 ) \n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR',color = 'r',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='o',s= 60, ax=ax1) \n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='s',s= 60, ax=ax1 ) \n", + "\n", + "\n", + "ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST',color = 'g' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='s', s= 60, ax=ax1 ) \n", + "#plt.plot(GT, GT, marker='x', linestyle='--', color='black') \n", + "\n", + "\n", + "# Plot the perfect estimation line\n", + "plt.plot([0, 2], [0, 2], linestyle='-', color='black')\n", + "\n", + "# Plot the JND thresholds (20% above and below the perfect estimation line)\n", + "x_vals = [0, 3]\n", + "y_vals_upper = [x * 1.05 for x in x_vals]\n", + "y_vals_lower = [x * 0.95 for x in x_vals]\n", + "plt.plot(x_vals, y_vals_upper, linestyle='--', color='black')\n", + "plt.plot(x_vals, y_vals_lower, linestyle='--', color='black')\n", + "\n", + "# Set the limits of the plot\n", + "plt.xlim(0, 2)\n", + "plt.ylim(0, 0.6)\n", + "# Set x-ticks with 0.5 intervals\n", + "# plt.xticks([0, 0.5, 1.0, 1.5, 2.0])\n", + "\n", + "plt.title ('EDT')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Ours'),\n", + " Line2D([0], [0], marker='', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL'),\n", + " Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "\n", + "\n", + "plt.legend(handles=legend_elements, loc='upper right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "e2850bdc-3dde-474a-b4c8-b637c32fe32c", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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06fp3r07AwYMAGDlypWsX7+emjVr8umnn5o5QiGEOVlaWuLu7o6npyfW1tbmDidLHj58yLp161i9ejXnzp2jbdu29O7dm/bt26dpS9GiRVmxYgWdO3c2Kk9ISMDDw4MpU6YwduzYdF+nd+/eVKlShWnTpgHQpUsXvL29mT792ZNG3n33Xe7du6f25D8pMjKSzZs3s3btWo4dO0azZs3o06cPXbt2xc7OLivfhixLSkrixo0bhIWFkZKSYnQsLi6O119/ncjISJydnXMthny18nV0dDQDBgxg/vz5uGa0stxTJk6cyLhx49TnUVFReHp60qpVK4oXL55boeY5ycnJ7N69m7Zt22L1vHnWJnD58mVOnz4NwKeffkqFChVITExUB2B/+OGH6q20F/Gsdv/777906dJR3fx069Yd1KhR44VfMy/Ia++3qUi7C1a7ExISuHHjBo6Ojtja2qY5rigK0dHRODk5odFozBBhxr799ls+/vhjXn75ZUJDQ5/b62JnZ5fml73hvTQc0+l0TJ8+nfXr13Pz5k2Sk5NJTEzE2dlZPdfS0hJra+s01/rxxx9ZvHgx169fJz4+nqSkJOrUqZNuguHs7MyYMWMYM2YMx44do1+/fowYMQI3N7dcn+yUkJCAnZ0dzZs3T/OeP3jwIFdf28CsiZGrqytarZa7d+8ald+9exd3d/c09S9dusTVq1d55ZVX1DJD16OlpSXnz5+nYsWKRufY2NikO4jXysqqQP0AySxztPvEiROMHj2aN998U127yDA7rV27dlR9vHrjo0ePaN26NUePHqVHjx5YWubcxzO9dteuXZvt23fxv/9N5LPPphfIMUXyOS9cClq7dTodGo0GCwsLLCzSDok1/Pw31MlLhg8fjpWVFcuWLcPb21vtGW/ZsmW6sabXxvPnzwNQoUIFLCws+PLLL/n+++/55ptvKF++PCVLlmTcuHEkJycbnfv092PNmjW8++67fP311zRp0gQnJye++uorjh49mm4sCQkJ/Prrr+ptvLp16zJ+/Hjatm2b699nCwsLNBpNup9lU322zfpJsra2pn79+uzdu1ct0+v17N271+jWmkG1atUICQnh9OnT6uPVV1+lVatWnD592qT3QUXmLVq0iD/++INdu3YBqV2lhsH1Tw66dnNzY/Xq1Zw9ezZHk6Jn8fb25tdftxbIpEgIYT6l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", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "################################################### graph without scale the KT and ST ########################################\n", + "##############################################################################################################################\n", + "##############################################################################################################################\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################## EDT with 5% JND threshold #############################################################\n", + "data = {'ours_KT': [0.53],\n", + " 'ours_MR':[0.44],\n", + " 'ours_UL':[0.51],\n", + " 'ours_ST':[ 1.00],\n", + " 'Kim19_KT': [0.86],\n", + " 'Kim19_MR': [0.53],\n", + " 'Kim19_UL': [0.66],\n", + " 'Kim19_ST': [1.55],\n", + " 'Kim21_KT': [0.45],\n", + " 'Kim21_MR':[0.49],\n", + " 'Kim21_UL':[0.51],\n", + " 'Kim21_ST': [0.96],\n", + " 'GT_KT':[0.41],\n", + " 'GT_MR':[0.21],\n", + " 'GT_UL':[0.20],\n", + " 'GT_ST':[0.22]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "GT = [0.41,0.21,0.20, 0.22]\n", + "\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='D', s= 60 ) \n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='o',s= 60, ax=ax1 ) \n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR',color = 'r',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='o',s= 60, ax=ax1) \n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='s',s= 60, ax=ax1 ) \n", + "\n", + "\n", + "ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST',color = 'g' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='s', s= 60, ax=ax1 ) \n", + "#plt.plot(GT, GT, marker='x', linestyle='--', color='black') \n", + "\n", + "\n", + "# Plot the perfect estimation line\n", + "plt.plot([0, 2], [0, 2], linestyle='-', color='black')\n", + "\n", + "# Plot the JND thresholds (5% above and below the perfect estimation line)\n", + "x_vals = [0, 3]\n", + "y_vals_upper = [x * 1.05 for x in x_vals]\n", + "y_vals_lower = [x * 0.95 for x in x_vals]\n", + "plt.plot(x_vals, y_vals_upper, linestyle='--', color='black')\n", + "plt.plot(x_vals, y_vals_lower, linestyle='--', color='black')\n", + "\n", + "# Set the limits of the plot\n", + "plt.xlim(0, 2)\n", + "plt.ylim(0, 0.6)\n", + "# Set x-ticks with 0.5 intervals\n", + "# plt.xticks([0, 0.5, 1.0, 1.5, 2.0])\n", + "\n", + "plt.title ('EDT')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Ours'),\n", + " Line2D([0], [0], marker='', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL'),\n", + " Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "\n", + "\n", + "plt.legend(handles=legend_elements, loc='upper right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "e1831ea8", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################## RT60 comparision plot#############################################################\n", + "data = {'ours_KT': [0.63],\n", + " 'ours_MR':[0.82],\n", + " 'ours_UL':[0.70],\n", + " 'ours_ST':[2.75],\n", + " 'Kim19_KT': [1.76],\n", + " 'Kim19_MR': [0.88],\n", + " 'Kim19_UL': [1.10],\n", + " 'Kim19_ST': [2.13],\n", + " 'Kim21_KT': [0.63],\n", + " 'Kim21_MR':[0.67],\n", + " 'Kim21_UL':[0.77],\n", + " 'Kim21_ST': [1.88],\n", + " 'GT_KT':[0.42],\n", + " 'GT_MR':[0.63],\n", + " 'GT_UL':[0.38],\n", + " 'GT_ST':[1.88]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "GT = [0.42,0.63,0.38, 1.88]\n", + "\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='D', s= 60 ) \n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='o',s= 60, ax=ax1 ) \n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT',color = 'yellow' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR',color = 'r',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR',color = 'r' ,edgecolors='black',marker='s', s= 60, ax=ax1 ) \n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='o',s= 60, ax=ax1) \n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL',color = 'b',edgecolors='black' ,marker='s',s= 60, ax=ax1 ) \n", + "\n", + "\n", + "ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='D', s= 60, ax=ax1) \n", + "ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST',color = 'g' ,edgecolors='black',marker='o', s= 60, ax=ax1) \n", + "ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST',color = 'g',edgecolors='black' ,marker='s', s= 60, ax=ax1 ) \n", + "plt.plot(GT,GT , marker='x', linestyle='--', color='black') \n", + "\n", + "plt.title('RT60')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Proposed'),\n", + " Line2D([0], [0], marker='x', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL'),\n", + " Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "\n", + "plt.legend(handles=legend_elements, loc='right')\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "66b60d01-0430-43c4-9be3-ea847dca4946", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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ggULcOLECRgZGSEiIgK6urr4888/4ebmhgcPHqBTp06IjIyErq6uchmFQoHZs2fD398fQghMnz4d27dvh56enga3hIiIqP5hEKpGsbGxWLZsGQBg8+bNaNOmDXJycuDu7o7U1FRYWVkhJiam2GjzT58+RWRkJAAgKCgIa9eu5duiiYiIqgEfn68meXl5ynHEpk6dinfffReFhYXw8fHBqVOnYGZmhtjYWLRs2bLYsqampoiNjcXJkyfx/vvv13TpREREDQbPCFUTXV1dREZGYuTIkVixYgWEEJg8eTL27t0LPT09REdH46233lK2T09PR1RUlPK7jY0NQxAREVE1YxCqRg4ODti1axf09PQQGBiIkJAQSCQSbN++Hc7Ozsp2165dg5OTE959913ExcVpsGIiIqKGhUFIzY4ePYrz58+rTNu4caNydPn169dj+PDhynknT56Es7Mzbt++DWtra9jY2NRovURERA0Zg5AapaWlwcvLC46OjpDJZACAqKgoTJ06FQCwcOFCTJo0Sdl+z5496N+/Px49eoQePXrgxIkTaNu2rSZKJyIiapAYhNRELpfj/fffR0ZGBmxtbeHo6Ijjx4/D19cXCoUCH374IRYtWqRs/+OPP2LEiBF4/vw5hgwZgiNHjqB58+aa2wAiIqIGiEFITb766iscOXIEhoaGiIiIwO3bt+Hh4YHc3Fy4u7tj/fr10NLSAlA05pifnx8UCgXGjx+P3bt3o1GjRhreAiIiooaHj8+rgUwmw5dffgmg6B4gIyMjODk5ITMzE7169cL27duVw2oAQJ8+ffDhhx/C3NwcS5YsUQYkIiIiqlkMQq8oIyMD7733nvLszvDhw9GnTx/cvXsXtra2iI6OhoGBAZ49ewYhBAwNDaGlpYUffviBAYiIiEjDeGnsFX333XdIS0tD+/btsWLFCnh6eiI5ORkWFhaIi4tD06ZN8ejRI7i4uGD06NHKkecZgoiIiDSPZ4Re0aJFi6Cvrw8PDw9MmTIFMpkMjRs3RkxMDKytrXH79m24ubnh6tWrMDExwfXr11VepEhERESawzNCr0gqlWLevHkICQlBREQEtLW1ERkZiS5duuD8+fNwdnbG1atX0bp1axw/fpwhiIiIqBZhEKqChw8f4rPPPsPz588BACtWrMDq1asBAGFhYRg4cCAOHz6MPn36IC0tDfb29khI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c+eUn8uXL2PNmjWVqvnvmjRpAi0tLWRmZqpM37JlCxISEuDs7Izt27fD1tYWv//+u0qbx48fo1mzZlX+bSJ6NQxCRPRK9PX14eHhgbVr10ImkyEhIQEpKSkAip6Mksvlav/NxMREKBQKrFixAr169YKtrS3+85//qLQp6be7du0KuVyOjIyMYuHOwsICANCuXbti9+y8HF5epqOjg/bt2+PSpUvF5nXt2hXz5s3DiRMn0LFjR/z888/KeTdu3EBubi66du1aqe0nIvVhECKiMuXl5SE9PV3l8/DhQwBFT1dt3rwZFy5cwM2bN7Ft2zbo6+vDysoKQNElr6NHj+L+/fvKZdTBxsYGBQUF+O6773Dz5k1s3boVGzZsUGljbW2N7OxsHDp0CA8fPsSzZ89ga2uL999/H2PHjsWuXbtw69YtnDp1CkFBQdi7dy8A4JNPPkFsbCyWL1+O1NRUfP/992VeFnvB1dUVx44dU36/desW5s2bh4SEBNy5cwf79+9Hamoq2rVrp2zz22+/oU2bNmjbtq2aeoaIKotBiIjKFBsbixYtWqh8/u///g8AYGJigk2bNqF3797o1KkTDh48iOjoaOX9NosXL8bt27fRtm1btV7+6dy5M1auXIlly5ahY8eO+OmnnxAUFKTSxtnZGR999BF8fHzQrFkzfPPNNwCKLleNHTsWM2fOhJ2dHTw9PXH69GlYWloCAHr16oVNmzZhzZo16Ny5M/bv34/58+eXW9PEiROxb98+PH36FABgYGCAK1eu4J133oGtrS0mTZqEadOmYfLkycplfvnlF/j5+amrW4ioCrSEEELTRRAR1QdeXl7o1q0b5s2bV27bixcvYsCAAbh27RqMjY1roDoiKgnPCBERqcm3336LRo0aVahtWloa/vWvfzEEEWkYzwgRERFRg8UzQkRERNRgMQgRERFRg8UgRERERA0WgxARERE1WAxCRERE1GAxCBEREVGDxSBEREREDRaDEBERETVYDEJERETUYP0/890aMo4MnN8AAAAASUVORK5CYII=", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################################## RT60 with 20% JND threshold ################################################################\n", + "# Data\n", + "data = {'ours_KT': [0.63],\n", + " 'ours_MR':[0.82],\n", + " 'ours_UL':[0.70],\n", + " 'ours_ST':[2.75],\n", + " 'Kim19_KT': [1.76],\n", + " 'Kim19_MR': [0.88],\n", + " 'Kim19_UL': [1.10],\n", + " 'Kim19_ST': [2.13],\n", + " 'Kim21_KT': [0.63],\n", + " 'Kim21_MR':[0.67],\n", + " 'Kim21_UL':[0.77],\n", + " 'Kim21_ST': [1.88],\n", + " 'GT_KT':[0.42],\n", + " 'GT_MR':[0.63],\n", + " 'GT_UL':[0.38],\n", + " 'GT_ST':[1.88]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "GT = [0.42,0.63,0.38, 1.88]\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT', color='yellow', edgecolors='black', marker='D', s=60)\n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT', color='yellow', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT', color='yellow', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR', color='red', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR', color='red', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR', color='red', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL', color='blue', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL', color='blue', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL', color='blue', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST', color='green', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST', color='green', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST', color='green', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "# Plot the perfect estimation line\n", + "plt.plot([0, 2], [0, 2], linestyle='-', color='black')\n", + "\n", + "# Plot the JND thresholds (20% above and below the perfect estimation line)\n", + "x_vals = [0, 3]\n", + "y_vals_upper = [x * 1.20 for x in x_vals]\n", + "y_vals_lower = [x * 0.80 for x in x_vals]\n", + "plt.plot(x_vals, y_vals_upper, linestyle='--', color='black')\n", + "plt.plot(x_vals, y_vals_lower, linestyle='--', color='black')\n", + "\n", + "# Set the limits of the plot\n", + "plt.xlim(0, 3)\n", + "plt.ylim(0, 2)\n", + "\n", + "# Set y-ticks with 0.5 intervals\n", + "plt.yticks([0, 0.5, 1.0, 1.5, 2.0])\n", + "\n", + "plt.title('RT60')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Ours'),\n", + " Line2D([0], [0], marker='', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL'),\n", + " Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "plt.legend(handles=legend_elements, loc='right')\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "903fbeeb-63cf-488d-a816-d9fb3fdba2a5", + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "<Figure size 640x480 with 1 Axes>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "################################################### graph without scale the KT and ST ########################################\n", + "##############################################################################################################################\n", + "##############################################################################################################################\n", + "import matplotlib.pyplot as plt\n", + "import pandas as pd\n", + "from matplotlib.lines import Line2D\n", + "############################################################## RT60 with 20% JND threshold ################################################################\n", + "# Data\n", + "data = {'ours_KT': [0.63],\n", + " 'ours_MR':[0.82],\n", + " 'ours_UL':[0.70],\n", + " 'ours_ST':[1.93],\n", + " 'Kim19_KT': [1.76],\n", + " 'Kim19_MR': [0.88],\n", + " 'Kim19_UL': [1.10],\n", + " 'Kim19_ST': [2.13],\n", + " 'Kim21_KT': [0.63],\n", + " 'Kim21_MR':[0.67],\n", + " 'Kim21_UL':[0.77],\n", + " 'Kim21_ST': [1.88],\n", + " 'GT_KT':[0.42],\n", + " 'GT_MR':[0.63],\n", + " 'GT_UL':[0.38],\n", + " 'GT_ST':[1.88]\n", + " }\n", + "\n", + "df = pd.DataFrame(data, columns=['ours_KT', 'ours_MR', 'ours_UL','ours_ST','Kim19_KT','Kim19_MR','Kim19_UL','Kim19_ST','Kim21_KT',\n", + " 'Kim21_MR','Kim21_UL','Kim21_ST','GT_KT','GT_MR', 'GT_UL','GT_ST'])\n", + "\n", + "GT = [0.42,0.63,0.38, 1.88]\n", + "ax1 = df.plot(kind='scatter', x='ours_KT', y='GT_KT', color='yellow', edgecolors='black', marker='D', s=60)\n", + "ax2 = df.plot(kind='scatter', x='Kim19_KT', y='GT_KT', color='yellow', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax3 = df.plot(kind='scatter', x='Kim21_KT', y='GT_KT', color='yellow', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax5 = df.plot(kind='scatter', x='ours_MR', y='GT_MR', color='red', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax6 = df.plot(kind='scatter', x='Kim19_MR', y='GT_MR', color='red', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax7 = df.plot(kind='scatter', x='Kim21_MR', y='GT_MR', color='red', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax9 = df.plot(kind='scatter', x='ours_UL', y='GT_UL', color='blue', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax10 = df.plot(kind='scatter', x='Kim19_UL', y='GT_UL', color='blue', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax11 = df.plot(kind='scatter', x='Kim21_UL', y='GT_UL', color='blue', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "ax13 = df.plot(kind='scatter', x='ours_ST', y='GT_ST', color='green', edgecolors='black', marker='D', s=60, ax=ax1)\n", + "ax14 = df.plot(kind='scatter', x='Kim19_ST', y='GT_ST', color='green', edgecolors='black', marker='o', s=60, ax=ax1)\n", + "ax15 = df.plot(kind='scatter', x='Kim21_ST', y='GT_ST', color='green', edgecolors='black', marker='s', s=60, ax=ax1)\n", + "\n", + "# Plot the perfect estimation line\n", + "plt.plot([0, 2], [0, 2], linestyle='-', color='black')\n", + "\n", + "# Plot the JND thresholds (20% above and below the perfect estimation line)\n", + "x_vals = [0, 3]\n", + "y_vals_upper = [x * 1.20 for x in x_vals]\n", + "y_vals_lower = [x * 0.80 for x in x_vals]\n", + "plt.plot(x_vals, y_vals_upper, linestyle='--', color='black')\n", + "plt.plot(x_vals, y_vals_lower, linestyle='--', color='black')\n", + "\n", + "# Set the limits of the plot\n", + "plt.xlim(0, 3)\n", + "plt.ylim(0, 2)\n", + "\n", + "# Set y-ticks with 0.5 intervals\n", + "plt.yticks([0, 0.5, 1.0, 1.5, 2.0])\n", + "\n", + "plt.title('RT60')\n", + "plt.xlabel('Estimated (s)')\n", + "plt.ylabel('Recorded (s)')\n", + "plt.grid(True)\n", + "\n", + "legend_elements = [Line2D([0], [0], lw=0,label='<Method>'),\n", + " Line2D([0], [0], marker='o', color='black', label='Kim19'),\n", + " Line2D([0], [0], marker='s', color='black', label='Kim20'),\n", + " Line2D([0], [0], marker='D', color='black', label='Ours'),\n", + " Line2D([0], [0], marker='', color='black', label='GT'),\n", + " Line2D([0], [0], lw=0, label='<Data>'),\n", + " Line2D([0], [0], lw=2, color='yellow', label='KT'),\n", + " Line2D([0], [0], lw=2, color='r', label='MR'),\n", + " Line2D([0], [0], lw=2, color='b', label='UL'),\n", + " Line2D([0], [0], lw=2, color='g', label='ST')]\n", + "\n", + "plt.legend(handles=legend_elements, loc='right')\n", + "plt.show()\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "19f04536-fba6-4453-a73b-859e7d095cf9", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (RIR_env)", + "language": "python", + "name": "rir_env" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/RIR_model-checkpoint.PNG b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/RIR_model-checkpoint.PNG new file mode 100644 index 0000000000000000000000000000000000000000..744b9496ff05446d7d490da08df5bba31d664085 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/.ipynb_checkpoints/RIR_model-checkpoint.PNG differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/.ipynb_checkpoints/main_MR-checkpoint.ipynb b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/.ipynb_checkpoints/main_MR-checkpoint.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..36da7e8ffd197f0248360a64ef56bd0e77bb3d59 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/.ipynb_checkpoints/main_MR-checkpoint.ipynb @@ -0,0 +1,311 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "84348fc9", + "metadata": {}, + "outputs": [], + "source": [ + " #!python --version" + ] + }, + { + "cell_type": "markdown", + "id": "7df1161c", + "metadata": {}, + "source": [ + "# RIR Deconvolution and Acoustic Parameters Estiation (EDT - RT60)" + ] + }, + { + "cell_type": "markdown", + "id": "57be83b0", + "metadata": {}, + "source": [ + "The recorded sound in unity platform for a certian scene is deconvolved to get the room acoustic propertits in room impulse response (RIR). Early decay time (EDT) and reverberation time (RT60) are calculated." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6f5c098a-8dc5-4005-b91c-00bb4e3a1382", + "metadata": {}, + "outputs": [], + "source": [ + "#!python -m ipykernel install --user --name RIR_env --display-name \"Python (RIR_env)\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d2d79d8c-ade2-4859-ad4e-aca5df8a4a12", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9e0abda2-30e8-4ea9-ab09-20aeca250fb3", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install scipy\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a4d644a9-54d2-4ab3-938a-4d100fb2d394", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install matplotlib\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a9aac7fd-3e4e-420e-856b-37cd04a16149", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install audiolazy\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "03f35449", + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.io import wavfile\n", + "import os\n", + "from scipy.io.wavfile import write as wavwrite\n", + "import numpy as np\n", + "from scipy import signal\n", + "from scipy.signal import fftconvolve\n", + "import matplotlib.pyplot as plt\n", + "from scipy.io.wavfile import read\n", + "from IPython.core.interactiveshell import InteractiveShell\n", + "InteractiveShell.ast_node_interactivity = \"all\"\n", + "from scipy.signal import resample\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "43bf15ee-83aa-4fc9-a752-59d4a1e65321", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sine sweep and inverse filter generated and saved as 16-bit WAV files.\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([0, 0, 0, ..., 0, 0, 0], dtype=int16),\n", + " array([0, 0, 0, ..., 0, 0, 0], dtype=int16))" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Most ideas from: https://github.com/maj4e/pyrirtool \n", + "import numpy as np\n", + "from scipy.io.wavfile import write as wavwrite\n", + "import scipy.signal as signal\n", + "from scipy.io.wavfile import read\n", + "from scipy.signal import resample\n", + "\n", + "def generate_exponential_sine_sweep(fs=48000, amplitude=0.5, duration=10, silenceAtStart=1, silenceAtEnd=1, sweeprange=[20, 20000], bit_depth=16):\n", + " \"\"\"\n", + " Generate an exponential sine sweep and its inverse filter, and save them as WAV files with the specified bit depth.\n", + " \n", + " Parameters:\n", + " - fs: Sampling rate (Hz)\n", + " - amplitude: Amplitude of the sine sweep\n", + " - duration: Duration of the sine sweep (seconds)\n", + " - silenceAtStart: Silence duration at the start (seconds)\n", + " - silenceAtEnd: Silence duration at the end (seconds)\n", + " - sweeprange: Start and end frequencies of the sweep (Hz)\n", + " - bit_depth: Bit depth of the output WAV files \n", + " \"\"\"\n", + " # define the frequency range for the sweep\n", + " f1 = max(sweeprange[0], 1) # start of sweep in Hz\n", + " f2 = sweeprange[1] if sweeprange[1] != 0 else int(fs / 2) # end of sweep in Hz\n", + " \n", + " w1 = 2 * np.pi * f1 / fs # start of sweep in rad/sample\n", + " w2 = 2 * np.pi * f2 / fs # end of sweep in rad/sample\n", + " \n", + " numSamples = duration * fs\n", + " taxis = np.arange(0, numSamples) / numSamples\n", + "\n", + " # generate the exponential sine sweep\n", + " lw = np.log(w2 / w1)\n", + " sinsweep = amplitude * np.sin(w1 * numSamples / lw * (np.exp(taxis * lw) - 1))\n", + " \n", + " # find the last zero crossing to avoid the need for fadeout\n", + " k = np.flipud(sinsweep)\n", + " error = 1\n", + " counter = 0\n", + " max_iterations = numSamples # to avoid infinite loop\n", + "\n", + " while error > 0.001 and counter < max_iterations:\n", + " error = np.abs(k[counter])\n", + " counter += 1\n", + "\n", + " k = k[counter:]\n", + " sinsweep_hat = np.flipud(k)\n", + " sinsweep = np.zeros(shape=(numSamples,))\n", + " sinsweep[:sinsweep_hat.shape[0]] = sinsweep_hat\n", + "\n", + " # compute the inverse filter\n", + " envelope = (w2 / w1) ** (-taxis)\n", + " invfilter = np.flipud(sinsweep) * envelope\n", + " scaling = np.pi * numSamples * (w1 / w2 - 1) / (2 * (w2 - w1) * np.log(w1 / w2)) * (w2 - w1) / np.pi\n", + " invfilter = invfilter / amplitude ** 2 / scaling\n", + "\n", + " # apply a Tukey window to taper the sine sweep\n", + " taperStart = signal.tukey(numSamples, 0.1) \n", + " sinsweep *= taperStart\n", + "\n", + " # add silence at the start and end\n", + " zerostart = np.zeros(shape=(silenceAtStart * fs,))\n", + " zeroend = np.zeros(shape=(silenceAtEnd * fs,))\n", + " sinsweep = np.concatenate((zerostart, sinsweep, zeroend))\n", + "\n", + " # normalize and convert to the specified bit depth\n", + " if bit_depth == 16:\n", + " sinsweep = np.int16(sinsweep / np.max(np.abs(sinsweep)) * 32767)\n", + " invfilter = np.int16(invfilter / np.max(np.abs(invfilter)) * 32767)\n", + " wavwrite('sine_sweep_16bit.wav', fs, sinsweep)\n", + " wavwrite('inverse_filter_16bit.wav', fs, invfilter)\n", + " \n", + " # write a copy in another folder for Matlab RIR analysis\n", + " wavwrite(r'add your bath\\RIR-evaluation-Matlab\\sounds\\MR_MDBNet\\sine_sweep_16bit.wav',fs,sinsweep)\n", + " wavwrite(r'add your bath\\RIR-evaluation-Matlab\\sounds\\MR_MDBNet\\inverse_filter_16bit.wav',fs,invfilter)\n", + " \n", + " else:\n", + " raise ValueError(\"Unsupported bit depth\")\n", + "\n", + " print(f'Sine sweep and inverse filter generated and saved as {bit_depth}-bit WAV files.')\n", + " return sinsweep, invfilter\n", + "\n", + "# Run the function to generate the sine sweep and its inverse\n", + "generate_exponential_sine_sweep(bit_depth=16)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9f4839a8-f8e5-45b0-b1ce-bc13a4740a90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs_recorded 48000\n", + "record (1291328, 2)\n", + "record_ch1 (1291328,)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\verim\\AppData\\Local\\Temp\\ipykernel_11888\\930783837.py:28: WavFileWarning: Chunk (non-data) not understood, skipping it.\n", + " f, rec = wavfile.read('./MR_Unity_bf.wav')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Room impulse response generated and saved as RIR_MR_Unity_bf.wav\n" + ] + } + ], + "source": [ + "\n", + "def deconvolve(recorded_sweep_path, inverse_filter_path, output_path):\n", + " \"\"\"\n", + " Perform deconvolution to generate a room impulse response from a recorded sweep.\n", + " \n", + " Parameters:\n", + " - recorded_sweep_path: Path to the recorded sweep audio file (WAV)\n", + " - inverse_filter_path: Path to the inverse filter audio file (WAV)\n", + " - output_path: Path to save the room impulse response (WAV)\n", + " \"\"\"\n", + " # load the recorded sweep and the inverse filter\n", + " fs, recorded_sweep = wavfile.read(recorded_sweep_path)\n", + " fs_inv, inverse_filter = wavfile.read(inverse_filter_path)\n", + " \n", + " \n", + " # perform deconvolution (convolution with the inverse filter)\n", + " rir = signal.fftconvolve(recorded_sweep, inverse_filter, mode='full')\n", + " \n", + " # normalize the impulse response\n", + " rir = rir / np.max(np.abs(rir))\n", + " \n", + " # save the room impulse response as a WAV file\n", + " wavfile.write(output_path, fs, rir)\n", + " \n", + " print(f'Room impulse response generated and saved as {output_path}')\n", + " return rir, fs\n", + "\n", + "#### Read the recorded file\n", + "f, rec = wavfile.read('./MR_Unity_bf.wav')\n", + "rec = np.array(rec)\n", + "print('fs_recorded', f)\n", + "# Truncate one channel for deconvolution\n", + "rec_ch1 = rec[:, 1]\n", + "print('record', rec.shape)\n", + "print('record_ch1', rec_ch1.shape)\n", + "wavwrite('MR_Unity_ch1_bf.wav', f, rec_ch1)\n", + "\n", + "# Deconvolve\n", + "recorded_sweep_path = 'MR_Unity_ch1_bf.wav' # Path to your recorded sweep file\n", + "inverse_filter_path = 'inverse_filter_16bit.wav' # Path to your inverse filter file\n", + "output_path = 'RIR_MR_Unity_bf.wav' # Path to save the room impulse response\n", + "\n", + "# Generate room impulse response\n", + "rir,fs = deconvolve(recorded_sweep_path, inverse_filter_path, output_path)\n", + "wavwrite(r'add your bath\\RIR-evaluation-Matlab\\sounds\\MR_MDBNet\\RIR_MR_Unity_bf.wav',fs,rir)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (RIR_env)", + "language": "python", + "name": "rir_env" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity.wav new file mode 100644 index 0000000000000000000000000000000000000000..cd66c606bfd79b6ac8c175e84f19f542b9df92f5 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_bf.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_bf.wav new file mode 100644 index 0000000000000000000000000000000000000000..8cddd999483d8c727885fa81da3b85f03dff48c8 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_bf.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_ch1.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_ch1.wav new file mode 100644 index 0000000000000000000000000000000000000000..894e18de458c150220081e8e4d78525426a15730 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_ch1.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_ch1_bf.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_ch1_bf.wav new file mode 100644 index 0000000000000000000000000000000000000000..d45db6ffc9c75cbd8fd2a3ace478ea0e64949b7b Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/MR_Unity_ch1_bf.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_MR_Unity.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_MR_Unity.wav new file mode 100644 index 0000000000000000000000000000000000000000..dede2b84e5fe8596df5793b51f01bc2993a88108 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_MR_Unity.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_MR_Unity_bf.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_MR_Unity_bf.wav new file mode 100644 index 0000000000000000000000000000000000000000..402b0341bb1f5972e89ea4005bf99018f53ce7f3 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_MR_Unity_bf.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_model.PNG b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_model.PNG new file mode 100644 index 0000000000000000000000000000000000000000..744b9496ff05446d7d490da08df5bba31d664085 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/RIR_model.PNG differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Algorithm_PeakDetection.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Algorithm_PeakDetection.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..813c962dc6639fb70bf322a5e1b47ee9cfdc437d Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Algorithm_PeakDetection.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Beamformers.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Beamformers.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b9c7f586487b412fc3ebcbbd0a448aba3fe395b1 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Beamformers.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Encoder_SAO.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Encoder_SAO.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd4d7c9dc4c671a9dcf7157fe8351b476e826888 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Encoder_SAO.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/FilterGeneration.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/FilterGeneration.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..85f99860f768c9c60c1c5e0dd594d291a3a0851f Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/FilterGeneration.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/MixingTime_Estimation.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/MixingTime_Estimation.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1af2f49f61e3e1302d0539a1c44395821dd6bce7 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/MixingTime_Estimation.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/RIR_Segmentation.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/RIR_Segmentation.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..042f9d35685cdcdae95d424e5438dccc975741d4 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/RIR_Segmentation.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Utility.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Utility.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ecb48f9fa246c2370a2fda2287fbdaf8741143ba Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/Utility.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/deconvolotion3.cpython-38.pyc b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/deconvolotion3.cpython-38.pyc new file mode 100644 index 0000000000000000000000000000000000000000..14fa06725780986dedd952ca96aed52d6dcf8261 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/__pycache__/deconvolotion3.cpython-38.pyc differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/inverse_filter_16bit.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/inverse_filter_16bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..01f1456817b5eba8cbe616c6330c5bcf9e7ab537 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/inverse_filter_16bit.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/main_MR.ipynb b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/main_MR.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..36da7e8ffd197f0248360a64ef56bd0e77bb3d59 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/main_MR.ipynb @@ -0,0 +1,311 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "id": "84348fc9", + "metadata": {}, + "outputs": [], + "source": [ + " #!python --version" + ] + }, + { + "cell_type": "markdown", + "id": "7df1161c", + "metadata": {}, + "source": [ + "# RIR Deconvolution and Acoustic Parameters Estiation (EDT - RT60)" + ] + }, + { + "cell_type": "markdown", + "id": "57be83b0", + "metadata": {}, + "source": [ + "The recorded sound in unity platform for a certian scene is deconvolved to get the room acoustic propertits in room impulse response (RIR). Early decay time (EDT) and reverberation time (RT60) are calculated." + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "6f5c098a-8dc5-4005-b91c-00bb4e3a1382", + "metadata": {}, + "outputs": [], + "source": [ + "#!python -m ipykernel install --user --name RIR_env --display-name \"Python (RIR_env)\"\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "d2d79d8c-ade2-4859-ad4e-aca5df8a4a12", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "9e0abda2-30e8-4ea9-ab09-20aeca250fb3", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install scipy\n" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "a4d644a9-54d2-4ab3-938a-4d100fb2d394", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install matplotlib\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "a9aac7fd-3e4e-420e-856b-37cd04a16149", + "metadata": {}, + "outputs": [], + "source": [ + "#!pip install audiolazy\n" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "03f35449", + "metadata": {}, + "outputs": [], + "source": [ + "from scipy.io import wavfile\n", + "import os\n", + "from scipy.io.wavfile import write as wavwrite\n", + "import numpy as np\n", + "from scipy import signal\n", + "from scipy.signal import fftconvolve\n", + "import matplotlib.pyplot as plt\n", + "from scipy.io.wavfile import read\n", + "from IPython.core.interactiveshell import InteractiveShell\n", + "InteractiveShell.ast_node_interactivity = \"all\"\n", + "from scipy.signal import resample\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "43bf15ee-83aa-4fc9-a752-59d4a1e65321", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sine sweep and inverse filter generated and saved as 16-bit WAV files.\n" + ] + }, + { + "data": { + "text/plain": [ + "(array([0, 0, 0, ..., 0, 0, 0], dtype=int16),\n", + " array([0, 0, 0, ..., 0, 0, 0], dtype=int16))" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Most ideas from: https://github.com/maj4e/pyrirtool \n", + "import numpy as np\n", + "from scipy.io.wavfile import write as wavwrite\n", + "import scipy.signal as signal\n", + "from scipy.io.wavfile import read\n", + "from scipy.signal import resample\n", + "\n", + "def generate_exponential_sine_sweep(fs=48000, amplitude=0.5, duration=10, silenceAtStart=1, silenceAtEnd=1, sweeprange=[20, 20000], bit_depth=16):\n", + " \"\"\"\n", + " Generate an exponential sine sweep and its inverse filter, and save them as WAV files with the specified bit depth.\n", + " \n", + " Parameters:\n", + " - fs: Sampling rate (Hz)\n", + " - amplitude: Amplitude of the sine sweep\n", + " - duration: Duration of the sine sweep (seconds)\n", + " - silenceAtStart: Silence duration at the start (seconds)\n", + " - silenceAtEnd: Silence duration at the end (seconds)\n", + " - sweeprange: Start and end frequencies of the sweep (Hz)\n", + " - bit_depth: Bit depth of the output WAV files \n", + " \"\"\"\n", + " # define the frequency range for the sweep\n", + " f1 = max(sweeprange[0], 1) # start of sweep in Hz\n", + " f2 = sweeprange[1] if sweeprange[1] != 0 else int(fs / 2) # end of sweep in Hz\n", + " \n", + " w1 = 2 * np.pi * f1 / fs # start of sweep in rad/sample\n", + " w2 = 2 * np.pi * f2 / fs # end of sweep in rad/sample\n", + " \n", + " numSamples = duration * fs\n", + " taxis = np.arange(0, numSamples) / numSamples\n", + "\n", + " # generate the exponential sine sweep\n", + " lw = np.log(w2 / w1)\n", + " sinsweep = amplitude * np.sin(w1 * numSamples / lw * (np.exp(taxis * lw) - 1))\n", + " \n", + " # find the last zero crossing to avoid the need for fadeout\n", + " k = np.flipud(sinsweep)\n", + " error = 1\n", + " counter = 0\n", + " max_iterations = numSamples # to avoid infinite loop\n", + "\n", + " while error > 0.001 and counter < max_iterations:\n", + " error = np.abs(k[counter])\n", + " counter += 1\n", + "\n", + " k = k[counter:]\n", + " sinsweep_hat = np.flipud(k)\n", + " sinsweep = np.zeros(shape=(numSamples,))\n", + " sinsweep[:sinsweep_hat.shape[0]] = sinsweep_hat\n", + "\n", + " # compute the inverse filter\n", + " envelope = (w2 / w1) ** (-taxis)\n", + " invfilter = np.flipud(sinsweep) * envelope\n", + " scaling = np.pi * numSamples * (w1 / w2 - 1) / (2 * (w2 - w1) * np.log(w1 / w2)) * (w2 - w1) / np.pi\n", + " invfilter = invfilter / amplitude ** 2 / scaling\n", + "\n", + " # apply a Tukey window to taper the sine sweep\n", + " taperStart = signal.tukey(numSamples, 0.1) \n", + " sinsweep *= taperStart\n", + "\n", + " # add silence at the start and end\n", + " zerostart = np.zeros(shape=(silenceAtStart * fs,))\n", + " zeroend = np.zeros(shape=(silenceAtEnd * fs,))\n", + " sinsweep = np.concatenate((zerostart, sinsweep, zeroend))\n", + "\n", + " # normalize and convert to the specified bit depth\n", + " if bit_depth == 16:\n", + " sinsweep = np.int16(sinsweep / np.max(np.abs(sinsweep)) * 32767)\n", + " invfilter = np.int16(invfilter / np.max(np.abs(invfilter)) * 32767)\n", + " wavwrite('sine_sweep_16bit.wav', fs, sinsweep)\n", + " wavwrite('inverse_filter_16bit.wav', fs, invfilter)\n", + " \n", + " # write a copy in another folder for Matlab RIR analysis\n", + " wavwrite(r'add your bath\\RIR-evaluation-Matlab\\sounds\\MR_MDBNet\\sine_sweep_16bit.wav',fs,sinsweep)\n", + " wavwrite(r'add your bath\\RIR-evaluation-Matlab\\sounds\\MR_MDBNet\\inverse_filter_16bit.wav',fs,invfilter)\n", + " \n", + " else:\n", + " raise ValueError(\"Unsupported bit depth\")\n", + "\n", + " print(f'Sine sweep and inverse filter generated and saved as {bit_depth}-bit WAV files.')\n", + " return sinsweep, invfilter\n", + "\n", + "# Run the function to generate the sine sweep and its inverse\n", + "generate_exponential_sine_sweep(bit_depth=16)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "9f4839a8-f8e5-45b0-b1ce-bc13a4740a90", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "fs_recorded 48000\n", + "record (1291328, 2)\n", + "record_ch1 (1291328,)\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "C:\\Users\\verim\\AppData\\Local\\Temp\\ipykernel_11888\\930783837.py:28: WavFileWarning: Chunk (non-data) not understood, skipping it.\n", + " f, rec = wavfile.read('./MR_Unity_bf.wav')\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Room impulse response generated and saved as RIR_MR_Unity_bf.wav\n" + ] + } + ], + "source": [ + "\n", + "def deconvolve(recorded_sweep_path, inverse_filter_path, output_path):\n", + " \"\"\"\n", + " Perform deconvolution to generate a room impulse response from a recorded sweep.\n", + " \n", + " Parameters:\n", + " - recorded_sweep_path: Path to the recorded sweep audio file (WAV)\n", + " - inverse_filter_path: Path to the inverse filter audio file (WAV)\n", + " - output_path: Path to save the room impulse response (WAV)\n", + " \"\"\"\n", + " # load the recorded sweep and the inverse filter\n", + " fs, recorded_sweep = wavfile.read(recorded_sweep_path)\n", + " fs_inv, inverse_filter = wavfile.read(inverse_filter_path)\n", + " \n", + " \n", + " # perform deconvolution (convolution with the inverse filter)\n", + " rir = signal.fftconvolve(recorded_sweep, inverse_filter, mode='full')\n", + " \n", + " # normalize the impulse response\n", + " rir = rir / np.max(np.abs(rir))\n", + " \n", + " # save the room impulse response as a WAV file\n", + " wavfile.write(output_path, fs, rir)\n", + " \n", + " print(f'Room impulse response generated and saved as {output_path}')\n", + " return rir, fs\n", + "\n", + "#### Read the recorded file\n", + "f, rec = wavfile.read('./MR_Unity_bf.wav')\n", + "rec = np.array(rec)\n", + "print('fs_recorded', f)\n", + "# Truncate one channel for deconvolution\n", + "rec_ch1 = rec[:, 1]\n", + "print('record', rec.shape)\n", + "print('record_ch1', rec_ch1.shape)\n", + "wavwrite('MR_Unity_ch1_bf.wav', f, rec_ch1)\n", + "\n", + "# Deconvolve\n", + "recorded_sweep_path = 'MR_Unity_ch1_bf.wav' # Path to your recorded sweep file\n", + "inverse_filter_path = 'inverse_filter_16bit.wav' # Path to your inverse filter file\n", + "output_path = 'RIR_MR_Unity_bf.wav' # Path to save the room impulse response\n", + "\n", + "# Generate room impulse response\n", + "rir,fs = deconvolve(recorded_sweep_path, inverse_filter_path, output_path)\n", + "wavwrite(r'add your bath\\RIR-evaluation-Matlab\\sounds\\MR_MDBNet\\RIR_MR_Unity_bf.wav',fs,rir)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python (RIR_env)", + "language": "python", + "name": "rir_env" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.19" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/sine_sweep_16bit.wav b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/sine_sweep_16bit.wav new file mode 100644 index 0000000000000000000000000000000000000000..54c0d175c64672b7f2a0cc817419446d1d9ba4a1 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/MR/sine_sweep_16bit.wav differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Measurement-Kitchen.pptx b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Measurement-Kitchen.pptx new file mode 100644 index 0000000000000000000000000000000000000000..7e9afacbcc7dc4601b662bab7afa1a7660779255 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Measurement-Kitchen.pptx differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Positions_in_Rooms.pptx b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Positions_in_Rooms.pptx new file mode 100644 index 0000000000000000000000000000000000000000..2116e328208372a24cfeadd9743b86a851c23c22 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Positions_in_Rooms.pptx differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Quick Guide for Working with Unity.pdf b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Quick Guide for Working with Unity.pdf new file mode 100644 index 0000000000000000000000000000000000000000..81b15f12fb31466d9fc72c90a04b30db9aab7979 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/Quick Guide for Working with Unity.pdf differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/RIR_model.PNG b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/RIR_model.PNG new file mode 100644 index 0000000000000000000000000000000000000000..744b9496ff05446d7d490da08df5bba31d664085 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/RIR_Analysis/RIR_model.PNG differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/ReadMe.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/ReadMe.txt new file mode 100644 index 0000000000000000000000000000000000000000..32ead9f2ab8be35fe011535783e0c8b4ccfafd14 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/ReadMe.txt @@ -0,0 +1,49 @@ +Conda Environment Setup: +conda install pytorch==2.0.0 torchvision==0.15.0 torchaudio==2.0.0 pytorch-cuda=11.8 -c pytorch -c nvidia +conda install -c conda-forge tqdm #optional +conda install -c conda-forge tensorboard #optional +conda install -c conda-forge scikit-image +conda install -c conda-forge scikit-learn +conda install -c conda-forge pandas +conda install -c conda-forge numpy +conda install -c conda-forge opencv +conda install matplotlib +-------------------------------------------------------------------------------- +For ESS sound generation and deconvolution within python env: +pip install numpy +pip install scipy +pip install matplotlib +pip install audiolazy + +Install MATAB with signal processing options to use IoSR Toolbox for EDT and RT60 measures + +############################################################ +***Note in enhance360.py (line 22) and infer360.py(line29) for Kitchen scene use baseline = 0.176 + +1- Compile the CUDA code: +nvcc -std=c++11 --ptxas-options=-v --compiler-options '-fPIC' -o lib_preproc.so --shared lib_mdbnet360.cu + +2- Enhance depth maps, use run_enhance360_job.sh , or run: +python enhance360.py Meeting shifted-disparity.png shifted_t.png new_shifted-disparity.png + +input --> origenal depth (shifted-disparity.png) +Scene --> Meeting +output --> enhanced depth (new_shifted-disparity.png) + +3- Predict the full 3D room of 360 RGB-D MR scene, use run_obj_MR_job.sh or run: +python infer360.py Meeting new_shifted-disparity.png shifted_t.png Meeting + +inputs --> depth: new_shifted-disparity.png and RGB: shifted_t.png +Scene --> Meeting +output --> Obj file with mtl wich defines the surface material properties of the 3D + +4- Import the obj with the corresponding mtl files to Unity with Steam Audio plug-in. + +5- RIR extraction: +- Use the python file main_MR.ipynb to: + a- Generate ESS audio saved as sine_sweep_16bit.wav. + b- Add this sound to Unity sound source then render and record the sound within MR room. ( Unity simulation settings provided in PDF file). + c- Convolve the recorded sound with the inferse filter of ESS, the RIR for the meeting room will be saved at RIR-evaluation-Matlab/sounds/MR_MDBNet + +6- EDT and RT60 evaulation: +- Use Main_Immersive_EDT_RT60.m, in the command window write: Main_Immersive_EDT_RT60 diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/new_shifted-disparity.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/new_shifted-disparity.png new file mode 100644 index 0000000000000000000000000000000000000000..3f9415e9af6c0f1eb94cd36dff6cf818b620ab51 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/new_shifted-disparity.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted-disparity-org.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted-disparity-org.png new file mode 100644 index 0000000000000000000000000000000000000000..5155ccf52f9c11450ada2a51abb517f8df857ce7 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted-disparity-org.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted-disparity.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted-disparity.png new file mode 100644 index 0000000000000000000000000000000000000000..b2ff1d41ae0a9372cc534ea2cfc46fb91742995a Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted-disparity.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted_t.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted_t.png new file mode 100644 index 0000000000000000000000000000000000000000..4184963e39d3a75dbceb6014884053e4c3841cf0 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Kitchen/shifted_t.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/new_shifted-disparity.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/new_shifted-disparity.png new file mode 100644 index 0000000000000000000000000000000000000000..be1b476ff6ca38de2e719cf7571ad4920c4442a3 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/new_shifted-disparity.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/shifted-disparity.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/shifted-disparity.png new file mode 100644 index 0000000000000000000000000000000000000000..875d9f288fdba144ed25390e82f392d142254eae Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/shifted-disparity.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/shifted_t.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/shifted_t.png new file mode 100644 index 0000000000000000000000000000000000000000..167d408542f64b454557a37aaf0fd7e6ed0f8d23 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Meeting/shifted_t.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/new_shifted-disparity.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/new_shifted-disparity.png new file mode 100644 index 0000000000000000000000000000000000000000..7215f1eb57c5506fe4920f19d67279daa03d2fd4 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/new_shifted-disparity.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/shifted-disparity.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/shifted-disparity.png new file mode 100644 index 0000000000000000000000000000000000000000..9419e69133ab89a33ba421ec43369719befaa3c9 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/shifted-disparity.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/shifted_t.png b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/shifted_t.png new file mode 100644 index 0000000000000000000000000000000000000000..6a0b96e552e7699284eb464eb324b6527c959c3d Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/data/Usability/shifted_t.png differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/enhance360.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/enhance360.py new file mode 100644 index 0000000000000000000000000000000000000000..746295cc9df9d11845c58f6c901f6ae8c0bd206b --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/enhance360.py @@ -0,0 +1,99 @@ +''' +This script used to enhance the depth maps by aligning them to e Cartesian axis and using canny edge detector +# Based on: https://gitlab.com/UnBVision/edgenet360/-/blob/master/enhance360.py?ref_type=heads +''' + + +import os +import argparse +import numpy as np +import cv2 +import matplotlib.pyplot as plt +from utils.py_cuda import lib_mdbnet360_setup, get_point_cloud +from utils.preproc import find_limits_v2, find_planes, fix_limits, fix_heigth_stanford + +## https://gitlab.com/UnBVision/edgenet360/-/blob/master/enhance360.py?ref_type=heads + +PI = 3.14159265 +DISP_SCALE = 2.0 +DISP_OFFSET = -120.0 + +#BASELINE=0.176 #baseline for Kitchen--> 0.176, studio--> 0.202 +BASELINE=0.264 # for meeting room and Usability +V_UNIT=0.02 +DATA_PATH = './data' + + +def process(depth_file, rgb_file, out_depth_file, baseline): + + print(depth_file) + print(rgb_file) + + point_cloud, depth_image = get_point_cloud(depth_file, baseline=baseline) + + bgr_image = cv2.imread(rgb_file, cv2.IMREAD_COLOR) + + edges_image = cv2.Canny(bgr_image, 30, 70) + + kernel = np.ones((5,5),np.uint8) + + thin_edges = cv2.dilate(edges_image,kernel,iterations = 1) + wide_edges = cv2.dilate(edges_image,kernel,iterations = 3) + + bilateral=cv2.bilateralFilter(bgr_image,3,75,75) + + new_depth_image, region_mask, edges_mask, inf_region_mask, close_region_mask = find_planes(point_cloud, bilateral, wide_edges, depth_image, thin_edges, baseline=baseline) + + cv2.imwrite(out_depth_file, new_depth_image) + + point_cloud, depth_image = get_point_cloud(out_depth_file, baseline=baseline) + + + ceil_height, floor_height, front_dist, back_dist, right_dist, left_dist = find_limits_v2(point_cloud) + + + fixed_depth = fix_limits(point_cloud, depth_image, + ceil_height, floor_height, front_dist, back_dist, right_dist, left_dist, + baseline=baseline) + + print("room height: %2.2f (%2.2f <> %2.2f)" % (ceil_height - floor_height, ceil_height, floor_height)) + print("room width: %2.2f (%2.2f <> %2.2f)" % ( right_dist - left_dist, right_dist , left_dist)) + print("room length: %2.2f (%2.2f <> %2.2f)" % ( front_dist - back_dist, front_dist , back_dist)) + + cv2.imwrite(out_depth_file, fixed_depth) + print("Finished!") + + +def parse_arguments(): + global DATA_PATH, DATASET + + print("\n360 depth maps enhancer\n") + + parser = argparse.ArgumentParser() + parser.add_argument("dataset", help="360 dataset dir", type=str) + parser.add_argument("depth_map", help="360 depth map", type=str) + parser.add_argument("rgb", help="360 rgb", type=str) + parser.add_argument("output", help="output file prefix", type=str) + parser.add_argument("--baseline", help="Stereo 360 camera baseline. Default 0.264", type=float, default=0.264, required=False) #baseline for Kitchen-->0.176, studio-->0.202 + parser.add_argument("--data_path", help="Data path. Default %s"%DATA_PATH, type=str, + default=DATA_PATH, required=False) + + args = parser.parse_args() + DATA_PATH = args.data_path + DATASET = args.dataset + + depth_map = os.path.join(DATA_PATH, DATASET, args.depth_map) + rgb_file = os.path.join(DATA_PATH,DATASET, args.rgb) + output = os.path.join(DATA_PATH, DATASET, args.output) + baseline = args.baseline + + return depth_map, rgb_file, output, baseline + +# Main Function +def Run(): + depth_map, rgb_file, output, baseline = parse_arguments() + process(depth_map, rgb_file, output, baseline) + + +if __name__ == '__main__': + Run() diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/infer360.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/infer360.py new file mode 100644 index 0000000000000000000000000000000000000000..244f41ecb692aa0c57aed02f08eea3077cdc6d72 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/infer360.py @@ -0,0 +1,441 @@ + +# Some ides from: https://gitlab.com/UnBVision/edgenet360/-/blob/master/infer360.py?ref_type=heads + +import argparse +import os +import numpy as np +import torch +import torch.nn.functional as F +from utils.py_cuda import lib_mdbnet360_setup, get_point_cloud, get_voxels, downsample_grid, get_ftsdf, downsample_limits +from utils.visual_utils import obj_export +from utils.spher_cubic_proj import spher_cubic_proj +from model.mdbnet import get_res_unet_rgb, get_2Dfeatures, get_activation +from utils.post_process import voxel_filter, voxel_fill, fill_limits_vox, instance_remover,remove_internal_voxels_v2 +import cv2 +import math + +os.environ['TF_CPP_MIN_VLOG_LEVEL'] = '3' +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' +CV_PI = 3.141592 + + +prediction_shape = (60,36,60) + + +DATA_PATH = './data' +#OUTPUT_PATH = './output/model_Y' +OUTPUT_PATH = './output' +WEIGHTS_PATH = './weights' +BASELINE = 0.264 # for meeting room and Usability +#BASELINE = 0.176 for Kitchen scene, 0.202 for Studio scene +V_UNIT = 0.02 +NETWORK = 'MDBNet' +FILTER = True +SMOOTHING = True +REMOVE_INTERNAL = False +MIN_VOXELS = 15 +TRIANGULAR_FACES = False +FILL_LIMITS = True +INNER_FACES = False +INCLUDE_TOP = False +SAVED_WEIGHTES_3D = "./weights/ResUNet_rgb_late_tanh_identity_fold1_2024-01-26.pth" +SAVED_WEIGHTES_2D ="./weights/2D_pretrained_late_tanh_identity_fold1_2024-01-26.pth" +PRE_TRAINED_MODEL = "./pretrained_segformer_b5_ade-640-640" +FUSION_LOC = 'late' +IMAGE_SIZE = (480, 640) +SENSOR_W = 640 # perspective image dim +SENSOR_H = 480 + + +def process(depth_file, rgb_file, out_prefix): + + print("Processing point cloud...") + + point_cloud, depth_image = get_point_cloud(depth_file, baseline=BASELINE) + print("point_cloud", point_cloud.shape) + + ceil_height, floor_height = np.max(point_cloud[:,:,wy]), np.min(point_cloud[:,:,wy]) + front_dist, back_dist = np.max(point_cloud[:,:,wz]), np.min(point_cloud[:,:,wz]) + right_dist, left_dist = np.max(point_cloud[:,:,wx]), np.min(point_cloud[:,:,wx]) + print ('floor_height', floor_height) + print("room height: %2.2f (%2.2f <> %2.2f)" % (ceil_height - floor_height, ceil_height, floor_height)) + print("room width: %2.2f (%2.2f <> %2.2f)" % ( right_dist - left_dist, right_dist , left_dist)) + print("room length: %2.2f (%2.2f <> %2.2f)" % ( front_dist - back_dist, front_dist , back_dist)) + + cam_hight = - floor_height + if ((DATASET == 'Kitchen') or (DATASET == 'kitchen') ): + average = (ceil_height + abs(floor_height)) / 2 + average_str = str(average) + decimal_pos = average_str.find('.') + result_str = average_str[:decimal_pos + 2] + result = float(result_str) + cam_hight = result + + + cam_back = 0.0 # un-used + print('CAM height:', cam_hight) + camx, camy, camz = -left_dist, cam_hight, -back_dist + + print('camx', camx) + print('camy', camy) + print('camz', camz) + lib_mdbnet360_setup(device=0, num_threads=1024, v_unit=V_UNIT, v_margin=0.24, f=518.8579, debug=0, cam_h = cam_hight, cam_b = cam_back) + + ######################################################################################################### + print("\nLoading %s..." % NETWORK) + model2D, img_processor = get_2Dfeatures(PRE_TRAINED_MODEL) + model = get_res_unet_rgb(FUSION_LOC) # 3D model + + # make device agnostic code + dev = 'cuda:0' + device = torch.device(dev) if torch.cuda.is_available() else torch.device("cpu") + # 1- load the saved state dict + state_dict_2d = torch.load(f=SAVED_WEIGHTES_2D) + state_dict_3d = torch.load(f=SAVED_WEIGHTES_3D) + + # 2- create a new state dict in which 'module.' prefix is removed 'if multple GPUs' + new_state_dict_2d = {k.replace('module.', ''): v for k, v in state_dict_2d.items()} + new_state_dict_3d = {k.replace('module.', ''): v for k, v in state_dict_3d.items()} + + # 3- load the new state dict to your model + model2D.load_state_dict(new_state_dict_2d) + model.load_state_dict(new_state_dict_3d) + + # send model to GPU + model2D = model2D.to(device) + model = model.to(device) + + ########################################################################################################################################### + + xs, ys, zs = prediction_shape + + pred_full = np.zeros((xs*2,ys,xs*2,12), dtype=np.float32) + flags_full = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + surf_full = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + + ### spherical to cubic projection + rgb_views,depth_views = spher_cubic_proj(depth_file, rgb_file, out_prefix) # return lists + + print("Inferring...") + + for (rgb_view_idx, rgb_filename) in (rgb_views): + print(f"RGB view: {rgb_view_idx}, RGB Filename: {rgb_filename}") + + view = rgb_view_idx + + rgb = cv2.imread(rgb_filename, cv2.IMREAD_COLOR) + + vox_grid, depth_mapping_3d = get_voxels(depth_image, point_cloud, depth_image.shape, + min_x=left_dist , max_x=right_dist , + min_y=floor_height , max_y=ceil_height , + min_z=back_dist , max_z=front_dist , + vol_number=view) + + vox_tsdf, vox_limits = get_ftsdf(depth_image, vox_grid, + min_x=left_dist , max_x=right_dist , + min_y=floor_height , max_y=ceil_height , + min_z=back_dist , max_z=front_dist , baseline=BASELINE, vol_number=view) + + vox_grid_down = downsample_grid(vox_grid) + + ################################################################# + print("Shape of depth_mapping:", depth_mapping_3d.shape) + depth_m = depth_mapping_3d.flatten() + valid_depth_values = np.where(depth_m>= 0) + print('valid_depth_values len', len(valid_depth_values)) + print('valid_depth_values shape', valid_depth_values) + print('depth_mapping[valid_depth_values].max',depth_m[valid_depth_values].max()) + print('depth_mapping[valid_depth_values].min',depth_m[valid_depth_values].min()) + + ############################################################## + depth_mapping = depth_mapping_3d.reshape(1,240*144*240) + rgb_v = cv2.imread(rgb_filename, cv2.IMREAD_COLOR) + # convert to tensor + rgb_t = torch.from_numpy(rgb_v.astype(np.float32).transpose((2, 0, 1)) / 255) + rgb_t = rgb_t.to(device) + + x= torch.from_numpy(vox_tsdf).reshape(1,1, 240, 144, 240).to(device) + # get the predictions + model.eval() + model2D.eval() + with torch.inference_mode(): + + # get the 2d feature maps from pretrained model + rgb_t = rgb_t.unsqueeze(0) + imgs = img_processor(images=rgb_t, return_tensors="pt").to(device) + + hook,activation = get_activation('linear_fuse') + model2D.decode_head.register_forward_hook(hook) + cls = model2D(**imgs) # predected 2d classes + classes_logits = cls.logits # logits from classification layer + feature2d = activation['linear_fuse'] # the activation maps befor the classification layer + + # upsample the output to match input images size + desired_size = IMAGE_SIZE + feature2d = F.interpolate(feature2d, size=desired_size, mode='bilinear', align_corners=True) + + # input the predicted 2D features to the 3D model alongside with depth data + + depth_3d = torch.from_numpy(depth_mapping).to(device) + print("Shape of rgb :", rgb_t.shape) + print("Shape of F-tsdf :", x.shape) + print("Shape of depth_3d:", depth_3d.shape) + + pred = model(rgb_t, x,feature2d, depth_3d, device).cpu() + + print("Shape of pred torch:", pred.shape) + # reshape the pred tensor to [60, 36, 60, 12] + pred_reshaped = pred.permute(2, 3, 4, 1, 0).contiguous().view(zs,ys,xs, 12) + pred_reshaped = pred_reshaped.numpy() + print("Shape of pred_reshaped numpy:", pred_reshaped.shape) + #################################################################################################### + flags_down = downsample_limits(vox_limits) + + print("Shape of flags_down:", flags_down.shape) + + # repeat the flags_down array along the last dimension + flags_down_repeated = np.repeat(flags_down[:, :, :, np.newaxis], 12, axis=3) + print("Shape of flags_down_repeated:", flags_down_repeated.shape) + fpred = pred_reshaped * flags_down_repeated + + print("Shape of fpred:", fpred.shape) + print("type of fpred:", fpred.dtype) + + ##################################################################### to visualise single view####################################################### + + if view==1: + pred_full_ = np.zeros((xs*2,ys,xs*2,12), dtype=np.float32) + flags_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + surf_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + + pred_full_[ zs:, :, xs//2:-xs//2] = fpred + surf_full_[ zs:, :, xs//2:-xs//2] = vox_grid_down + + + + elif view==2: + pred_full_ = np.zeros((xs*2,ys,xs*2,12), dtype=np.float32) + flags_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + surf_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + + pred_full_[zs//2:-zs//2, :, xs:] = np.flip(np.swapaxes(fpred,0,2),axis=0) + surf_full_[zs//2:-zs//2, :, xs:] = np.flip(np.swapaxes(vox_grid_down,0,2),axis=0) + + + + elif view==3: + pred_full_ = np.zeros((xs*2,ys,xs*2,12), dtype=np.float32) + flags_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + surf_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + + pred_full_[:zs, :, xs//2:-xs//2] = np.flip(fpred,axis=[0,2]) + surf_full_[:zs, :, xs//2:-xs//2] = np.flip(vox_grid_down,axis=[0,2]) + + + elif view == 4: + pred_full_ = np.zeros((xs*2,ys,xs*2,12), dtype=np.float32) + flags_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + surf_full_ = np.zeros((xs*2,ys,xs*2), dtype=np.uint8) + + pred_full_[zs//2:-zs//2, :, :xs] = np.flip(np.swapaxes(fpred,0,2),axis=2) + surf_full_[zs//2:-zs//2, :, :xs] = np.flip(np.swapaxes(vox_grid_down,0,2),axis=2) + + + + y_pred_ = np.argmax(pred_full_, axis=-1) + # fill camera position + y_pred_[zs-4:zs+4,0,xs-4:xs+4] = 2 + + if FILTER: + print("Filtering...") + y_pred_ = voxel_filter(y_pred_) + + if MIN_VOXELS>1: + print("Removing small instances (<%d voxels)..." % MIN_VOXELS) + y_pred_ = instance_remover(y_pred_, min_size=MIN_VOXELS) + + if SMOOTHING: + print("Smoothing...") + y_pred_ = voxel_fill(y_pred_) + + if REMOVE_INTERNAL: + print("Removing internal voxels of the objects...") + y_pred_ = remove_internal_voxels_v2(y_pred_, camx, camy, camz, V_UNIT) + + print(" ") + + out_file = out_prefix + '_surface_'+str(view) + print("Exporting surface to %s.obj" % out_file) + obj_export(out_file, surf_full_, surf_full_.shape, camx, camy, camz, V_UNIT, include_top=INCLUDE_TOP, + triangular=TRIANGULAR_FACES) + + out_file = out_prefix+'_prediction_'+str(view) + print("Exporting prediction to %s.obj" % out_file) + obj_export(out_file, y_pred_, (xs*2,ys,zs*2), camx, camy, camz, V_UNIT, include_top=INCLUDE_TOP, + triangular=TRIANGULAR_FACES, + inner_faces=INNER_FACES) + + ###################################################################################################################################### + + ############################################################################### Full Prediction ###################################### + + + if view==1: + pred_full[ zs:, :, xs//2:-xs//2] += fpred + surf_full[ zs:, :, xs//2:-xs//2] |= vox_grid_down + + elif view==2: + pred_full[zs//2:-zs//2, :, xs:] += np.flip(np.swapaxes(fpred,0,2),axis=0) # addition proba then we take the argmax y_pred + surf_full[zs//2:-zs//2, :, xs:] |= np.flip(np.swapaxes(vox_grid_down,0,2),axis=0) + + elif view==3: + pred_full[:zs, :, xs//2:-xs//2] += np.flip(fpred,axis=[0,2]) + surf_full[:zs, :, xs//2:-xs//2] |= np.flip(vox_grid_down,axis=[0,2]) + + elif view == 4: + pred_full[zs//2:-zs//2, :, :xs] += np.flip(np.swapaxes(fpred,0,2),axis=2) + surf_full[zs//2:-zs//2, :, :xs] |= np.flip(np.swapaxes(vox_grid_down,0,2),axis=2) + + print("Combining all views...") + y_pred = np.argmax(pred_full, axis=-1) + + # fill camera position + y_pred[zs-4:zs+4,0,xs-4:xs+4] = 2 + + # remove ceiling and floor from the prediction and set them in post-processing with find limits + y_pred[y_pred == 1] = 0 + y_pred[y_pred == 2] = 0 + + ################################################################################ + + if FILTER: + print("Filtering...") + y_pred = voxel_filter(y_pred) + + if MIN_VOXELS>1: + print("Removing small instances (<%d voxels)..." % MIN_VOXELS) + y_pred = instance_remover(y_pred, min_size=MIN_VOXELS) + + if SMOOTHING: + print("Smoothing...") + y_pred = voxel_fill(y_pred) + + if FILL_LIMITS: + print("Completing room limits...") + print('limits max x,min x,max z,min z:', int(right_dist/V_UNIT), int(left_dist/V_UNIT),int(front_dist/V_UNIT), int(back_dist/V_UNIT)) + y_pred = fill_limits_vox(y_pred,int(right_dist/V_UNIT), int(left_dist/V_UNIT),int(front_dist/V_UNIT), int(back_dist/V_UNIT)) + + if REMOVE_INTERNAL: + print("Removing internal voxels of the objects...") + y_pred = remove_internal_voxels_v2(y_pred, camx, camy, camz, V_UNIT) + + print(" ") + + out_file = out_prefix + '_surface' + print("Exporting surface to %s.obj" % out_file) + obj_export(out_file, surf_full, surf_full.shape, camx, camy, camz, V_UNIT, include_top=INCLUDE_TOP, + triangular=TRIANGULAR_FACES) + + out_file = out_prefix+'_prediction' + print("Exporting prediction to %s.obj" % out_file) + obj_export(out_file, y_pred, (xs*2,ys,zs*2), camx, camy, camz, V_UNIT, include_top=True, + triangular=TRIANGULAR_FACES, + inner_faces=INNER_FACES) + + print("Finished!\n") + +def parse_arguments(): + global DATA_PATH, DATASET, OUTPUT_PATH, BASELINE, V_UNIT, NETWORK, FILTER, SMOOTHING, \ + FILL_LIMITS, MIN_VOXELS, TRIANGULAR_FACES, WEIGHTS_PATH, INCLUDE_TOP, REMOVE_INTERNAL, INNER_FACES + + print("\nSemantic Scene Completion Inference from 360 depth maps\n") + + parser = argparse.ArgumentParser() + parser.add_argument("dataset", help="360 dataset dir", type=str) + parser.add_argument("depth_map", help="360 depth map", type=str) + parser.add_argument("rgb_file", help="rgb", type=str) + parser.add_argument("output", help="output file prefix", type=str) + parser.add_argument("--baseline", help="Stereo 360 camera baseline. Default %5.3f"%BASELINE, type=float, + default=BASELINE, required=False) + parser.add_argument("--v_unit", help="Voxel size. Default %5.3f" % V_UNIT, type=float, + default=V_UNIT, required=False) + parser.add_argument("--network", help="Network to be used. Default %s" % NETWORK, type=str, + default=NETWORK, choices=["EdgeNet", "USSCNet"], required=False) + parser.add_argument("--filter", help="Apply 3D low-pass filter? Default yes.", type=str, + default="Y", choices=["Y", "y", "N", "n"], required=False) + parser.add_argument("--smoothing", help="Apply smoothing (fill small holes)? Default yes.", type=str, + default="Y", choices=["Y", "y", "N", "n"], required=False) + parser.add_argument("--fill_limits", help="Fill walls on room limits? Default yes.", type=str, + default="Y", choices=["Y", "y", "N", "n"], required=False) + parser.add_argument("--remove_internal", help="Remove internal voxels? Default no.", type=str, + default="N", choices=["Y", "y", "N", "n"], required=False) + parser.add_argument("--inner_faces", help="Include inner faces of objects? Default no.", type=str, + default="N", choices=["Y", "y", "N", "n"], required=False) + parser.add_argument("--min_voxels", help="Minimum number of voxels per object instance. Default %d."%MIN_VOXELS, type=int, + default=MIN_VOXELS, required=False) + parser.add_argument("--triangular", help="Use triangular faces? Default No.", type=str, + default="N", choices=["Y", "y", "N", "n"], required=False) + parser.add_argument("--include_top", help="Include top (ceiling) in output model? Default No.", type=str, + default="N", choices=["Y", "y", "N", "n"], required=False) + parser.add_argument("--data_path", help="Data path. Default %s"%DATA_PATH, type=str, + default=DATA_PATH, required=False) + parser.add_argument("--output_path", help="Output path. Default %s"%OUTPUT_PATH, type=str, + default=OUTPUT_PATH, required=False) + parser.add_argument("--weights_path", help="Weights path. Default %s"%WEIGHTS_PATH, type=str, + default=WEIGHTS_PATH, required=False) + + args = parser.parse_args() + + BASELINE = args.baseline + V_UNIT = args.v_unit + NETWORK = args.network + FILTER = args.filter in ["Y", "y"] + SMOOTHING = args.smoothing in ["Y", "y"] + REMOVE_INTERNAL = args.remove_internal in ["Y", "y"] + FILL_LIMITS = args.fill_limits in ["Y", "y"] + INNER_FACES = args.inner_faces in ["Y", "y"] + MIN_VOXELS = args.min_voxels + TRIANGULAR_FACES = args.triangular in ["Y", "y"] + INCLUDE_TOP = args.include_top in ["Y", "y"] + DATA_PATH = args.data_path + OUTPUT_PATH = args.output_path + WEIGHTS_PATH = args.weights_path + + DATASET = args.dataset + depth_map = os.path.join(DATA_PATH, DATASET, args.depth_map) + rgb_file = os.path.join(DATA_PATH, DATASET, args.rgb_file) + output = os.path.join(OUTPUT_PATH, args.output) + + fail = False + if not os.path.isfile(depth_map): + print("Depth map file not found:", depth_map) + fail = True + + if not os.path.isfile(rgb_file): + print("RGB file not found:", rgb_file ) + fail = True + + if fail: + print("Exiting...\n") + exit(0) + + if not os.path.isdir(OUTPUT_PATH): + os.makedirs(OUTPUT_PATH, exist_ok=True) + + print("360 depth map:", depth_map) + print("360 rgb: ", rgb_file) + print("Output prefix:", output) + print("Baseline: ", BASELINE) + print("V_Unit: ", V_UNIT) + print("") + + return depth_map, rgb_file, output + +# Main Function +def Run(): + depth_map, rgb_file, output = parse_arguments() + process(depth_map, rgb_file, output) + + +if __name__ == '__main__': + Run() diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/model/mdbnet.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/model/mdbnet.py new file mode 100644 index 0000000000000000000000000000000000000000..ea7463aef0061d65705ebd8647b3042cdd21af7a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/model/mdbnet.py @@ -0,0 +1,589 @@ +import torch +import torch.nn as nn +import torch.nn.functional as F +from transformers import SegformerImageProcessor, SegformerForSemanticSegmentation +from torchvision import transforms +import math + +''' +This code for early and late fusion for RGB features +''' + +####################################### For 2D Feature Extractuion and Downsampling Network ####################################### +""" +PCR +From Front to Rear: 3D Semantic Scene Completion through Planar Convolution and Attention-based Network +implemented based on: +https://github.com/waterljwant/SSC/blob/master/models/DDR.py +""" + +import torch +import torch.nn as nn +from torch.nn import functional as F + + + +class BasicDDR3d(nn.Module): + def __init__(self, c, k=3, dilation=1, stride=1, residual=True): + super(BasicDDR3d, self).__init__() + d = dilation + p = k // 2 * d + s = stride + + self.conv_1x1xk = nn.Conv3d(c, c, (1, 1, k), stride=(1, 1, s), padding=(0, 0, p), bias=True, dilation=(1, 1, d)) + self.conv_1xkx1 = nn.Conv3d(c, c, (1, k, 1), stride=(1, s, 1), padding=(0, p, 0), bias=True, dilation=(1, d, 1)) + self.conv_kx1x1 = nn.Conv3d(c, c, (k, 1, 1), stride=(s, 1, 1), padding=(p, 0, 0), bias=True, dilation=(d, 1, 1)) + self.residual = residual + + def forward(self, x): + y = self.conv_1x1xk(x) + y = F.relu(y, inplace=True) + y = self.conv_1xkx1(y) + y = F.relu(y, inplace=True) + y = self.conv_kx1x1(y) + y = F.relu(y + x, inplace=True) if self.residual else F.relu(y, inplace=True) + return y + + +class BottleneckDDR3d(nn.Module): + def __init__(self, c_in, c, c_out, kernel=3, stride=1, dilation=1, residual=True): + super(BottleneckDDR3d, self).__init__() + s = stride + k = kernel + d = dilation + p = k // 2 * d + self.conv_in = nn.Conv3d(c_in, c, kernel_size=1, bias=False) + self.conv1x3x3 = nn.Conv3d(c, c, (1, k, k), stride=s, padding=(0, p, p), bias=True, dilation=(1, d, d)) + self.conv3x3x1 = nn.Conv3d(c, c, (k, k, 1), stride=s, padding=(p, p, 0), bias=True, dilation=(d, d, 1)) + self.conv3x1x3 = nn.Conv3d(c, c, (k, 1, k), stride=s, padding=(p, 0, p), bias=True, dilation=(d, 1, d)) + self.conv_out = nn.Conv3d(c, c_out, kernel_size=1, bias=False) + self.residual = residual + + def forward(self, x): + y0 = self.conv_in(x) + y0 = F.relu(y0, inplace=True) + + y1 = self.conv1x3x3(y0) + y1 = F.relu(y1, inplace=True) + + y2 = self.conv3x3x1(y1) + y1 + y2 = F.relu(y2, inplace=True) + + y3 = self.conv3x1x3(y2) + y2 + y1 + y3 = F.relu(y3, inplace=True) + + y = self.conv_out(y3) + + y = F.relu(y + x, inplace=True) if self.residual else F.relu(y, inplace=True) + return y + + +class DownsampleBlock3d(nn.Module): + def __init__(self, c_in, c_out, k=3, s=2, p=1): + super(DownsampleBlock3d, self).__init__() + self.conv = nn.Conv3d(c_in, c_out-c_in, kernel_size=k, stride=s, padding=p, bias=False) + self.pool = nn.MaxPool3d(2, stride=2) + + def forward(self, x): + y = torch.cat([self.conv(x), self.pool(x)], 1) + y = F.relu(y, inplace=True) + return y + +################################################################################################################################ +############################################### ITRM Block ##################################################################### +################################################################################################################################ +class BatchNormRelu(nn.Module): + def __init__(self, in_c): + super().__init__() + + self.bn = nn.BatchNorm3d(in_c) + self.relu = nn.ReLU() + + def forward(self, inputs): + x = self.bn(inputs) + x = self.relu(x) + return x + + +class ResBlock(nn.Module): + def __init__(self, in_c, out_c, kernel_size, dilation=1): + super().__init__() + + self.br11 = BatchNormRelu(out_c) + + self.c11 = nn.Conv3d(in_channels=out_c, out_channels=out_c, kernel_size=kernel_size, + padding='same', dilation=dilation) + self.br12 = BatchNormRelu(out_c) + self.c12 = nn.Conv3d(in_channels=out_c, out_channels=out_c, kernel_size=kernel_size, + padding='same', dilation=dilation) + + self.tanh = nn.Tanh() + + def forward(self, inputs): + x = self.br11(inputs) + x = self.c11(x) + x = self.br12(x) + x = self.c12(x) + tn_inp = self.tanh(inputs) + + add1 = tn_inp + x + + return add1 + +#################################################################################################################################################### +########################################################## 2D to 3D projection and 3D Feature extraction ########################################### +#################################################################################################################################################### + +class Feature_extractor_2D_3D(nn.Module): + def __init__(self): + super(Feature_extractor_2D_3D, self).__init__() + self.pooling = nn.AvgPool3d(kernel_size=3, padding=1, stride=1) + + self.rgb_feature3d = nn.Sequential( + DownsampleBlock3d(12, 16),#ch_in + BottleneckDDR3d(c_in=16, c=4, c_out=16, dilation=1, residual=True), + DownsampleBlock3d(16, 32), #ch_out + BottleneckDDR3d(c_in=32, c=8, c_out=32, dilation=1, residual=True), + ) + + def project2D_3D(self,feature2d,depth_3d,device): + ch= 12 + b, c, h, w = feature2d.shape + input_ = feature2d.view(b, c, -1) + output = torch.zeros((b, c, 240*144*240)).to(device) #--> output: torch.Size([1, 12, 8294400]) + + indexo, indexi = torch.where(depth_3d > 0) #--> indexi represent pixel index where depth value existed + output[indexo, :, depth_3d[indexo, indexi]] = input_[indexo, :, indexi] # depth_3d[indexo, indexi] include the voxel index value(vox_idx) + output = output.view(b, c, 240, 144, 240).contiguous() + + return output + + def forward(self,feature2d,depth_3d, location, device): + + ''' + #project 2D feature to 3D space + ''' + segres = self.project2D_3D(feature2d, depth_3d,device) + + # initt the 3D features + pool = self.pooling(segres) + zero = (segres == 0).float() + pool = pool * zero + segres = segres + pool + + if location == 'late': + ''' + extract 3D feature and downsamling + ''' + seg_3dfea = self.rgb_feature3d(segres) + + else: # if location early + seg_3dfea = segres + + return seg_3dfea + +#################################################################################################################################################### +########################################################## 2D Features extraction using pretrained model ########################################### +#################################################################################################################################################### + +def get_2Dfeatures(pretrained_model): + num_classes = 12 + #model_name = "./pretrained_segformer_b5_ade-640-640" + model_name = pretrained_model + id2label = {0:'Empty', 1:'ceiling', 2:'floor', 3:'wall', 4:'window', 5:'chair', 6:'bed', 7:'sofa', 8:'table', 9:'tvs', 10:'furn', 11:'objs'} + label2id = {v: k for k, v in id2label.items()} + + # load the pretrained model + seg_model = SegformerForSemanticSegmentation.from_pretrained(model_name, id2label=id2label, label2id=label2id, return_dict=True, ignore_mismatched_sizes=True) + image_processor = SegformerImageProcessor.from_pretrained(model_name, do_rescale=False) # the images alredy scaled within the dataloder + + # Freeze encoder parameters. + for param in seg_model.segformer.encoder.parameters(): + param.requires_grad = False + + # Update the classifier layer in the decoder to produce the num_classes outputs + seg_model.decode_head.classifier = nn.Conv2d(in_channels=768, out_channels=num_classes, kernel_size=(1, 1), stride=(1, 1)) + + return seg_model,image_processor + + +###################################################################### +def get_activation(name): # to get the feature maps 'activations' + activation = {} + def hook(model, input, output): + if isinstance(output, tuple): + output = output[0] + activation[name] = output.detach() + return hook,activation +#################################################################################################################################################### +########################################################## ResUNet + Depth + RGB ################################################################# +#################################################################################################################################################### + +class BuildResUNet_RGB(nn.Module): + + def __init__(self, location): + + super(BuildResUNet_RGB, self).__init__() + kernel_size = (3, 3, 3) + + # Projection and feature extraction + self.feature2D3D = Feature_extractor_2D_3D() + self.location = location + + # Trunk part + """ Encoders """ + if self.location =='early': + self.r1 = ResBlock(12, 12, kernel_size=kernel_size) + self.mp1 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + self.conv2 = nn.Conv3d(12, 16, kernel_size=(3, 3, 3), padding='same') + self.r2 = ResBlock(16, 16, kernel_size=kernel_size) + self.mp2 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + else: # if location late + self.conv1 = nn.Conv3d(1, 8, kernel_size=(3, 3, 3), padding='same') + self.r1 = ResBlock(8, 8, kernel_size=kernel_size) + self.mp1 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + self.conv2 = nn.Conv3d(8, 16, kernel_size=(3, 3, 3), padding='same') + self.r2 = ResBlock(16, 16, kernel_size=kernel_size) + self.mp2 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + ## U part. + self.conv3 = nn.Conv3d(16, 32, kernel_size=(3, 3, 3), padding='same') + self.r3 = ResBlock(32, 32, kernel_size=(3, 3, 3)) + self.mp3 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + self.conv4 = nn.Conv3d(32, 64, kernel_size=(3, 3, 3), padding='same') + self.r4 = ResBlock(64, 64, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + self.r5 = ResBlock(64, 64, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + self.mp5 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + self.conv6 = nn.Conv3d(64, 128, kernel_size=(3, 3, 3), padding='same') + self.r6 = ResBlock(128, 128, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + self.r7 = ResBlock(128, 128, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + + """ Transpose 1 """ + self.trans1 = nn.ConvTranspose3d(in_channels=128, out_channels=64, kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + + + """ Decoders 1 , 2 """ + self.conv7 = nn.Conv3d(128, 64, (3, 3, 3), padding='same') + self.d1 = ResBlock(64, 64, kernel_size=(3, 3, 3)) + + self.d2 = ResBlock(64, 64, kernel_size=(3, 3, 3)) + + """ Transpose 2 """ + + self.trans2 = nn.ConvTranspose3d(in_channels=64, out_channels=32, kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + """ Decoder 3 """ + self.conv8 = nn.Conv3d(64, 32, (3, 3, 3), padding='same') + self.d3 = ResBlock(32, 32, kernel_size=(3, 3, 3)) + + """ fin """ + self.f1 = nn.Conv3d(48, 16, kernel_size=1, padding='same') + self.f2 = nn.Conv3d(16, 16, kernel_size=1, padding='same') + self.f3 = nn.Conv3d(16, 12, kernel_size=1, padding='same') + self.relu = nn.ReLU() + + + def forward(self, rgb, inputs,feature2d, depth_3d, device): + + # Projection from 2D to 3D and feature extraction + sematic_feat_3D = self.feature2D3D(feature2d, depth_3d,self.location, device) + + """ Encoders """ + ################################################################################# + if self.location == 'early': + # fuse (by add) 3d sematic features to the F-TSDF + inputs = inputs + sematic_feat_3D + add1 = self.r1(inputs) + mp1 = self.mp1(add1) # 12 + conv2 = self.conv2(mp1) + add2 = self.r2(conv2) + mp2 = self.mp2(add2) # 16 + #print("mp2", mp2.size()) + + conv3 = self.conv3(mp2) + add3 = self.r3(conv3) # 32 + mp3 = self.mp3(add3) + #print("mp3", mp3.size()) + + conv4 = self.conv4(mp3) + add4 = self.r4(conv4) # 64 + add5 = self.r5(add4) + mp5 = self.mp5(add5) + #print("mp5", mp5.size()) + + conv6 = self.conv6(mp5) + add6 = self.r6(conv6) # 128 + #print("add6", add6.size()) + + add7 = self.r7(add6) + #print("add7", add7.size()) + + trans1 = self.trans1(add7) # 64 + #print("trans1", trans1.size()) + + """ Concat""" + concat1 = torch.cat([trans1, add5], axis=1) # 128 + #print("concat1", concat1.size()) + + """ Decoders """ + ########################################################################## + conv7 = self.conv7(concat1) # 64 + + d1 = self.d1(conv7) + #print("d1", d1.size()) + + d2 = self.d2(d1) + #print("d2", d2.size()) + + trans2 = self.trans2(d2) # 32 + #print("trans2", trans2.size()) + + """ Concat""" + concat2 = torch.cat([trans2, add3], axis=1) # 64 + #print("concat2", concat2.size()) + + conv8 = self.conv8(concat2) + d3 = self.d3(conv8) ## 32 + #print("d3", d3.size()) + + concat3 = torch.cat([d3, mp2], axis=1) # 48 + #print("concat3", concat3.size()) + + """ output """ + f1 = self.f1(concat3) + f1 = self.relu(f1) + #print("f1", f1.size()) + + f2 = self.f2(f1) + f2 = self.relu(f2) + #print("f2", f2.size()) + + f3 = self.f3(f2) + #print("f3", f3.size()) + + output = f3 + + else: # if location late + conv1 = self.conv1(inputs) + add1 = self.r1(conv1) + mp1 = self.mp1(add1) # 8 + #print("mp1", mp1.size()) + + conv2 = self.conv2(mp1) + add2 = self.r2(conv2) + mp2 = self.mp2(add2) # 16 + #print("mp2", mp2.size()) + + conv3 = self.conv3(mp2) + add3 = self.r3(conv3) # 32 + mp3 = self.mp3(add3) + #print("mp3", mp3.size()) + + conv4 = self.conv4(mp3) + add4 = self.r4(conv4) # 64 + add5 = self.r5(add4) + mp5 = self.mp5(add5) + #print("mp5", mp5.size()) + + conv6 = self.conv6(mp5) + add6 = self.r6(conv6) # 128 + #print("add6", add6.size()) + + add7 = self.r7(add6) + #print("add7", add7.size()) + + trans1 = self.trans1(add7) # 64 + #print("trans1", trans1.size()) + + """ Concat""" + concat1 = torch.cat([trans1, add5], axis=1) # 128 + #print("concat1", concat1.size()) + + """ Decoders """ + ########################################################################## + conv7 = self.conv7(concat1) # 64 + + d1 = self.d1(conv7) + #print("d1", d1.size()) + + d2 = self.d2(d1) + #print("d2", d2.size()) + + trans2 = self.trans2(d2) # 32 + #print("trans2", trans2.size()) + + """ Concat""" + concat2 = torch.cat([trans2, add3], axis=1) # 64 + #print("concat2", concat2.size()) + + conv8 = self.conv8(concat2) + ################################################################################# + # fuse (by add) 3d sematic features to the F-TSDF + conv8 = conv8 + sematic_feat_3D + ################################################################################# + d3 = self.d3(conv8) ## 32 + + #print("d3", d3.size()) + + concat3 = torch.cat([d3, mp2], axis=1) # 48 + #print("concat3", concat3.size()) + + """ output """ + f1 = self.f1(concat3) + f1 = self.relu(f1) + #print("f1", f1.size()) + + f2 = self.f2(f1) + f2 = self.relu(f2) + #print("f2", f2.size()) + + f3 = self.f3(f2) + #print("f3", f3.size()) + + output = f3 + + return output + + +def get_res_unet_rgb(location): + return BuildResUNet_RGB(location) + +#################################################################################################################################################### +########################################################## ResUNet_Depth Only ###################################################################### +#################################################################################################################################################### +class BuildResUNet(nn.Module): + def __init__(self): + super(BuildResUNet, self).__init__() + kernel_size = (3, 3, 3) + + # Trunk part + """ Encoders """ + self.conv1 = nn.Conv3d(1, 8, kernel_size=(3, 3, 3), padding='same') + self.r1 = ResBlock(8, 8, kernel_size=kernel_size) + self.mp1 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + self.conv2 = nn.Conv3d(8, 16, kernel_size=(3, 3, 3), padding='same') + self.r2 = ResBlock(16, 16, kernel_size=kernel_size) + self.mp2 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + ## Now start U part. + self.conv3 = nn.Conv3d(16, 32, kernel_size=(3, 3, 3), padding='same') + self.r3 = ResBlock(32, 32, kernel_size=(3, 3, 3)) + self.mp3 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + self.conv4 = nn.Conv3d(32, 64, kernel_size=(3, 3, 3), padding='same') + self.r4 = ResBlock(64, 64, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + self.r5 = ResBlock(64, 64, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + self.mp5 = nn.MaxPool3d(kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + self.conv6 = nn.Conv3d(64, 128, kernel_size=(3, 3, 3), padding='same') + self.r6 = ResBlock(128, 128, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + self.r7 = ResBlock(128, 128, kernel_size=(3, 3, 3), dilation=1) # Dilation rate + + """ Transpose 1 """ + self.trans1 = nn.ConvTranspose3d(in_channels=128, out_channels=64, kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + """ Decoders 1 , 2 """ + self.conv7 = nn.Conv3d(128, 64, (3, 3, 3), padding='same') + self.d1 = ResBlock(64, 64, kernel_size=(3, 3, 3)) + + self.d2 = ResBlock(64, 64, kernel_size=(3, 3, 3)) + + """ Transpose 2 """ + + self.trans2 = nn.ConvTranspose3d(in_channels=64, out_channels=32, kernel_size=(2, 2, 2), stride=(2, 2, 2)) + + """ Decoder 3 """ + self.conv8 = nn.Conv3d(64, 32, (3, 3, 3), padding='same') + self.d3 = ResBlock(32, 32, kernel_size=(3, 3, 3)) + + """ fin """ + self.f1 = nn.Conv3d(48, 16, kernel_size=1, padding='same') + self.f2 = nn.Conv3d(16, 16, kernel_size=1, padding='same') + self.f3 = nn.Conv3d(16, 12, kernel_size=1, padding='same') + self.relu = nn.ReLU() + + + def forward(self, inputs): + + """ Encoders """ + conv1 = self.conv1(inputs) + add1 = self.r1(conv1) + mp1 = self.mp1(add1) # 8 + #print("mp1", mp1.size()) + + conv2 = self.conv2(mp1) + add2 = self.r2(conv2) + mp2 = self.mp2(add2) # 16 + #print("mp2", mp2.size()) + + conv3 = self.conv3(mp2) + add3 = self.r3(conv3) # 32 + mp3 = self.mp3(add3) + #print("mp3", mp3.size()) + + conv4 = self.conv4(mp3) + add4 = self.r4(conv4) # 64 + add5 = self.r5(add4) + mp5 = self.mp5(add5) + #print("mp5", mp5.size()) + + conv6 = self.conv6(mp5) + add6 = self.r6(conv6) # 128 + #print("add6", add6.size()) + + add7 = self.r7(add6) + #print("add7", add7.size()) + + trans1 = self.trans1(add7) # 64 + #print("trans1", trans1.size()) + + """ Concat""" + concat1 = torch.cat([trans1, add5], axis=1) # 128 + #print("concat1", concat1.size()) + + """ Decoders """ + conv7 = self.conv7(concat1) + d1 = self.d1(conv7) # 64 + #print("d1", d1.size()) + + d2 = self.d2(d1) + #print("d2", d2.size()) + + trans2 = self.trans2(d2) # 64 + #print("trans2", trans2.size()) + + """ Concat""" + concat2 = torch.cat([trans2, add3], axis=1) # 64 + #print("concat2", concat2.size()) + + conv8 = self.conv8(concat2) + d3 = self.d3(conv8) # 32 + #print("d3", d3.size()) + + concat3 = torch.cat([d3, mp2], axis=1) # 48 + #print("concat3", concat3.size()) + + """ output """ + f1 = self.f1(concat3) + f1 = self.relu(f1) + #print("f1", f1.size()) + + f2 = self.f2(f1) + f2 = self.relu(f2) + #print("f2", f2.size()) + + f3 = self.f3(f2) + #print("f3", f3.size()) + output = f3 + return output + + +def get_res_unet(): + return BuildResUNet() + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/README.md b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/README.md new file mode 100644 index 0000000000000000000000000000000000000000..6ab26e3fdffcb43c7e743b481164e6940d668fdb --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/README.md @@ -0,0 +1,77 @@ +--- +license: other +tags: +- vision +- image-segmentation +datasets: +- scene_parse_150 +widget: +- src: https://huggingface.co/datasets/hf-internal-testing/fixtures_ade20k/resolve/main/ADE_val_00000001.jpg + example_title: House +- src: https://huggingface.co/datasets/hf-internal-testing/fixtures_ade20k/resolve/main/ADE_val_00000002.jpg + example_title: Castle +--- + +# SegFormer (b5-sized) model fine-tuned on ADE20k + +SegFormer model fine-tuned on ADE20k at resolution 640x640. It was introduced in the paper [SegFormer: Simple and Efficient Design for Semantic Segmentation with Transformers](https://arxiv.org/abs/2105.15203) by Xie et al. and first released in [this repository](https://github.com/NVlabs/SegFormer). + +Disclaimer: The team releasing SegFormer did not write a model card for this model so this model card has been written by the Hugging Face team. + +## Model description + +SegFormer consists of a hierarchical Transformer encoder and a lightweight all-MLP decode head to achieve great results on semantic segmentation benchmarks such as ADE20K and Cityscapes. The hierarchical Transformer is first pre-trained on ImageNet-1k, after which a decode head is added and fine-tuned altogether on a downstream dataset. + +## Intended uses & limitations + +You can use the raw model for semantic segmentation. See the [model hub](https://huggingface.co/models?other=segformer) to look for fine-tuned versions on a task that interests you. + +### How to use + +Here is how to use this model to classify an image of the COCO 2017 dataset into one of the 1,000 ImageNet classes: + +```python +from transformers import SegformerFeatureExtractor, SegformerForSemanticSegmentation +from PIL import Image +import requests + +feature_extractor = SegformerFeatureExtractor.from_pretrained("nvidia/segformer-b5-finetuned-ade-512-512") +model = SegformerForSemanticSegmentation.from_pretrained("nvidia/segformer-b5-finetuned-ade-512-512") + +url = "http://images.cocodataset.org/val2017/000000039769.jpg" +image = Image.open(requests.get(url, stream=True).raw) + +inputs = feature_extractor(images=image, return_tensors="pt") +outputs = model(**inputs) +logits = outputs.logits # shape (batch_size, num_labels, height/4, width/4) +``` + +For more code examples, we refer to the [documentation](https://huggingface.co/transformers/model_doc/segformer.html#). + +### License + +The license for this model can be found [here](https://github.com/NVlabs/SegFormer/blob/master/LICENSE). + +### BibTeX entry and citation info + +```bibtex +@article{DBLP:journals/corr/abs-2105-15203, + author = {Enze Xie and + Wenhai Wang and + Zhiding Yu and + Anima Anandkumar and + Jose M. Alvarez and + Ping Luo}, + title = {SegFormer: Simple and Efficient Design for Semantic Segmentation with + Transformers}, + journal = {CoRR}, + volume = {abs/2105.15203}, + year = {2021}, + url = {https://arxiv.org/abs/2105.15203}, + eprinttype = {arXiv}, + eprint = {2105.15203}, + timestamp = {Wed, 02 Jun 2021 11:46:42 +0200}, + biburl = {https://dblp.org/rec/journals/corr/abs-2105-15203.bib}, + bibsource = {dblp computer science bibliography, https://dblp.org} +} +``` diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/config.json b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/config.json new file mode 100644 index 0000000000000000000000000000000000000000..3cf1f37a73b0e34d1fd6fda13760f9037a91c46e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/config.json @@ -0,0 +1,372 @@ +{ + "architectures": [ + "SegformerForSemanticSegmentation" + ], + "attention_probs_dropout_prob": 0.0, + "classifier_dropout_prob": 0.1, + "decoder_hidden_size": 768, + "depths": [ + 3, + 6, + 40, + 3 + ], + "downsampling_rates": [ + 1, + 4, + 8, + 16 + ], + "drop_path_rate": 0.1, + "hidden_act": "gelu", + "hidden_dropout_prob": 0.0, + "hidden_sizes": [ + 64, + 128, + 320, + 512 + ], + "id2label": { + "0": "wall", + "1": "building", + "2": "sky", + "3": "floor", + "4": "tree", + "5": "ceiling", + "6": "road", + "7": "bed ", + "8": "windowpane", + "9": "grass", + "10": "cabinet", + "11": "sidewalk", + "12": "person", + "13": "earth", + "14": "door", + "15": "table", + "16": "mountain", + "17": "plant", + "18": "curtain", + "19": "chair", + "20": "car", + "21": "water", + "22": "painting", + "23": "sofa", + "24": "shelf", + "25": "house", + "26": "sea", + "27": "mirror", + "28": "rug", + "29": "field", + "30": "armchair", + "31": "seat", + "32": "fence", + "33": "desk", + "34": "rock", + "35": "wardrobe", + "36": "lamp", + "37": "bathtub", + "38": "railing", + "39": "cushion", + "40": "base", + "41": "box", + "42": "column", + "43": "signboard", + "44": "chest of drawers", + "45": "counter", + "46": "sand", + "47": "sink", + "48": "skyscraper", + "49": "fireplace", + "50": "refrigerator", + "51": "grandstand", + "52": "path", + "53": "stairs", + "54": "runway", + "55": "case", + "56": "pool table", + "57": "pillow", + "58": "screen door", + "59": "stairway", + "60": "river", + "61": "bridge", + "62": "bookcase", + "63": "blind", + "64": "coffee table", + "65": "toilet", + "66": "flower", + "67": "book", + "68": "hill", + "69": "bench", + "70": "countertop", + "71": "stove", + "72": "palm", + "73": "kitchen island", + "74": "computer", + "75": "swivel chair", + "76": "boat", + "77": "bar", + "78": "arcade machine", + "79": "hovel", + "80": "bus", + "81": "towel", + "82": "light", + "83": "truck", + "84": "tower", + "85": "chandelier", + "86": "awning", + "87": "streetlight", + "88": "booth", + "89": "television receiver", + "90": "airplane", + "91": "dirt track", + "92": "apparel", + "93": "pole", + "94": "land", + "95": "bannister", + "96": "escalator", + "97": "ottoman", + "98": "bottle", + "99": "buffet", + "100": "poster", + "101": "stage", + "102": "van", + "103": "ship", + "104": "fountain", + "105": "conveyer belt", + "106": "canopy", + "107": "washer", + "108": "plaything", + "109": "swimming pool", + "110": "stool", + "111": "barrel", + "112": "basket", + "113": "waterfall", + "114": "tent", + "115": "bag", + "116": "minibike", + "117": "cradle", + "118": "oven", + "119": "ball", + "120": "food", + "121": "step", + "122": "tank", + "123": "trade name", + "124": "microwave", + "125": "pot", + "126": "animal", + "127": "bicycle", + "128": "lake", + "129": "dishwasher", + "130": "screen", + "131": "blanket", + "132": "sculpture", + "133": "hood", + "134": "sconce", + "135": "vase", + "136": "traffic light", + "137": "tray", + "138": "ashcan", + "139": "fan", + "140": "pier", + "141": "crt screen", + "142": "plate", + "143": "monitor", + "144": "bulletin board", + "145": "shower", + "146": "radiator", + "147": "glass", + "148": "clock", + "149": "flag" + }, + "image_size": 224, + "initializer_range": 0.02, + "label2id": { + "airplane": 90, + "animal": 126, + "apparel": 92, + "arcade machine": 78, + "armchair": 30, + "ashcan": 138, + "awning": 86, + "bag": 115, + "ball": 119, + "bannister": 95, + "bar": 77, + "barrel": 111, + "base": 40, + "basket": 112, + "bathtub": 37, + "bed ": 7, + "bench": 69, + "bicycle": 127, + "blanket": 131, + "blind": 63, + "boat": 76, + "book": 67, + "bookcase": 62, + "booth": 88, + "bottle": 98, + "box": 41, + "bridge": 61, + "buffet": 99, + "building": 1, + "bulletin board": 144, + "bus": 80, + "cabinet": 10, + "canopy": 106, + "car": 20, + "case": 55, + "ceiling": 5, + "chair": 19, + "chandelier": 85, + "chest of drawers": 44, + "clock": 148, + "coffee table": 64, + "column": 42, + "computer": 74, + "conveyer belt": 105, + "counter": 45, + "countertop": 70, + "cradle": 117, + "crt screen": 141, + "curtain": 18, + "cushion": 39, + "desk": 33, + "dirt track": 91, + "dishwasher": 129, + "door": 14, + "earth": 13, + "escalator": 96, + "fan": 139, + "fence": 32, + "field": 29, + "fireplace": 49, + "flag": 149, + "floor": 3, + "flower": 66, + "food": 120, + "fountain": 104, + "glass": 147, + "grandstand": 51, + "grass": 9, + "hill": 68, + "hood": 133, + "house": 25, + "hovel": 79, + "kitchen island": 73, + "lake": 128, + "lamp": 36, + "land": 94, + "light": 82, + "microwave": 124, + "minibike": 116, + "mirror": 27, + "monitor": 143, + "mountain": 16, + "ottoman": 97, + "oven": 118, + "painting": 22, + "palm": 72, + "path": 52, + "person": 12, + "pier": 140, + "pillow": 57, + "plant": 17, + "plate": 142, + "plaything": 108, + "pole": 93, + "pool table": 56, + "poster": 100, + "pot": 125, + "radiator": 146, + "railing": 38, + "refrigerator": 50, + "river": 60, + "road": 6, + "rock": 34, + "rug": 28, + "runway": 54, + "sand": 46, + "sconce": 134, + "screen": 130, + "screen door": 58, + "sculpture": 132, + "sea": 26, + "seat": 31, + "shelf": 24, + "ship": 103, + "shower": 145, + "sidewalk": 11, + "signboard": 43, + "sink": 47, + "sky": 2, + "skyscraper": 48, + "sofa": 23, + "stage": 101, + "stairs": 53, + "stairway": 59, + "step": 121, + "stool": 110, + "stove": 71, + "streetlight": 87, + "swimming pool": 109, + "swivel chair": 75, + "table": 15, + "tank": 122, + "television receiver": 89, + "tent": 114, + "toilet": 65, + "towel": 81, + "tower": 84, + "trade name": 123, + "traffic light": 136, + "tray": 137, + "tree": 4, + "truck": 83, + "van": 102, + "vase": 135, + "wall": 0, + "wardrobe": 35, + "washer": 107, + "water": 21, + "waterfall": 113, + "windowpane": 8 + }, + "layer_norm_eps": 1e-06, + "mlp_ratios": [ + 4, + 4, + 4, + 4 + ], + "model_type": "segformer", + "num_attention_heads": [ + 1, + 2, + 5, + 8 + ], + "num_channels": 3, + "num_encoder_blocks": 4, + "patch_sizes": [ + 7, + 3, + 3, + 3 + ], + "reshape_last_stage": true, + "sr_ratios": [ + 8, + 4, + 2, + 1 + ], + "strides": [ + 4, + 2, + 2, + 2 + ], + "torch_dtype": "float32", + "transformers_version": "4.12.0.dev0" +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/gitattributes.txt b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/gitattributes.txt new file mode 100644 index 0000000000000000000000000000000000000000..6d34772f5ca361021038b404fb913ec8dc0b1a5a --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/gitattributes.txt @@ -0,0 +1,27 @@ +*.7z filter=lfs diff=lfs merge=lfs -text +*.arrow filter=lfs diff=lfs merge=lfs -text +*.bin filter=lfs diff=lfs merge=lfs -text +*.bin.* filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.ftz filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.h5 filter=lfs diff=lfs merge=lfs -text +*.joblib filter=lfs diff=lfs merge=lfs -text +*.lfs.* filter=lfs diff=lfs merge=lfs -text +*.model filter=lfs diff=lfs merge=lfs -text +*.msgpack filter=lfs diff=lfs merge=lfs -text +*.onnx filter=lfs diff=lfs merge=lfs -text +*.ot filter=lfs diff=lfs merge=lfs -text +*.parquet filter=lfs diff=lfs merge=lfs -text +*.pb filter=lfs diff=lfs merge=lfs -text +*.pt filter=lfs diff=lfs merge=lfs -text +*.pth filter=lfs diff=lfs merge=lfs -text +*.rar filter=lfs diff=lfs merge=lfs -text +saved_model/**/* filter=lfs diff=lfs merge=lfs -text +*.tar.* filter=lfs diff=lfs merge=lfs -text +*.tflite filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zstandard filter=lfs diff=lfs merge=lfs -text +*tfevents* filter=lfs diff=lfs merge=lfs -text diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/preprocessor_config.json b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/preprocessor_config.json new file mode 100644 index 0000000000000000000000000000000000000000..1efbd610426f44e03bec08100613c5ea9a057a87 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/preprocessor_config.json @@ -0,0 +1,18 @@ +{ + "do_normalize": true, + "do_resize": true, + "feature_extractor_type": "SegformerFeatureExtractor", + "image_mean": [ + 0.485, + 0.456, + 0.406 + ], + "image_std": [ + 0.229, + 0.224, + 0.225 + ], + "reduce_labels": true, + "resample": 2, + "size": 640 +} diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/pytorch_model.bin b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/pytorch_model.bin new file mode 100644 index 0000000000000000000000000000000000000000..2aa1d4f33a43842a92bdb42c6166ea38f7c1e003 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/pretrained_segformer_b5_ade-640-640/pytorch_model.bin differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_enhance360_job.sh b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_enhance360_job.sh new file mode 100644 index 0000000000000000000000000000000000000000..4e4a3d1bcf4145cbb9b6503561783c1f0e87574e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_enhance360_job.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +#SBATCH --nodes=1 +#SBATCH --gres=gpu:1 +#SBATCH --time=00:60:00 # walltime + +python enhance360.py Kitchen shifted-disparity.png shifted_t.png new_shifted-disparity.png +# python enhance360.py Kitchen 'model_Y/KT_disp_by_depth.png' 'model_Y/KT-t.png' 'model_Y/enhanced_KT_disp_by_depth.png' \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_KT_job.sh b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_KT_job.sh new file mode 100644 index 0000000000000000000000000000000000000000..1306f51c62f8dfd02debcb5e2a430cd898f6a117 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_KT_job.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +#SBATCH --nodes=1 +#SBATCH --gres=gpu:1 +#SBATCH --time=00:60:00 # walltime + +python infer360.py Kitchen new_shifted-disparity.png shifted_t.png Kitchen +# python infer360.py 'Kitchen/model_Y' 'KT_disp_by_depth.png' 'KT-t.png' 'Kitchen_model_Y' \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_MR_job.sh b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_MR_job.sh new file mode 100644 index 0000000000000000000000000000000000000000..3264719cd005188b1bc89e36d27d277d8e1e898d --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_MR_job.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +#SBATCH --nodes=1 +#SBATCH --gres=gpu:1 +#SBATCH --time=00:60:00 # walltime + +python infer360.py Meeting new_shifted-disparity.png shifted_t.png Meeting +# python infer360.py 'Meeting/model_Y' 'MR_disp_by_depth.png' 'MR-t.png' 'Meeting_model_Y' \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_Usability_job.sh b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_Usability_job.sh new file mode 100644 index 0000000000000000000000000000000000000000..f3a4a12e5b92d48f90d9d3e394d1017cc6735b9e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/run_obj_Usability_job.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +#SBATCH --nodes=1 +#SBATCH --gres=gpu:1 +#SBATCH --time=00:60:00 # walltime + +python infer360.py Usability new_shifted-disparity.png shifted_t.png Usability +# python infer360.py 'Usability/model_Y' 'UL_disp_by_depth.png' 'UL-t.png' 'Usability_model_Y' \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/src/lib_mdbnet360.cu b/Mona-SSC/Mona-SSC/MDBNet360_GDP/src/lib_mdbnet360.cu new file mode 100644 index 0000000000000000000000000000000000000000..a62308625f0b20a5cc22c29229fce098343bbf34 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/src/lib_mdbnet360.cu @@ -0,0 +1,2495 @@ +/* + MDBNet data preprocessing adaped to 360 degrees images + Author: Mona Alawadh June,2024 + Based on ideas from : https://gitlab.com/UnBVision/edgenet360/-/tree/master/src?ref_type=heads + and https://github.com/shurans/sscnet +*/ + +#include <iostream> +#include <fstream> +#include <algorithm> +#include <vector> +#include <stdlib.h> +#include <math.h> +#include <string.h> +#include <chrono> + +using namespace std; +using namespace std::chrono; + +typedef high_resolution_clock::time_point clock_tick; +#define MIN(X, Y) (((X) <= (Y)) ? (X) : (Y)) +#define MAX(X, Y) (((X) >= (Y)) ? (X) : (Y)) + +// Voxel information +float vox_unit = 0.02; +float vox_margin = 0.24; +int vox_size_x = 240; +int vox_size_y = 144; +int vox_size_z = 240; + +// Camera information +float f = 518.85; +float sensor_w = 640; +float sensor_h = 480; + +// GPU parameters +int NUM_THREADS = 1024; +int DEVICE = 0; +int debug = 0; +float cam_back_ = 1.0; +float cam_height_ = 1.0; + +// GPU Variables +float* parameters_GPU; +#define VOX_UNIT (0) +#define VOX_MARGIN (1) +#define VOX_SIZE_X (2) +#define VOX_SIZE_Y (3) +#define VOX_SIZE_Z (4) +#define CAM_F (5) +#define SENSOR_W (6) +#define SENSOR_H (7) +#define GO_BACK (8) +#define CAM_HEIGHT (9) + +#define FLOOR_OFFSET (0.00) +//VOX_LIMITS +#define OUT_OF_FOV (4) +#define OUT_OF_ROOM (3) +#define OCCLUDED (2) +#define OCCUPIED (1) +#define EMPTY_VISIBLE (0) + +#define NUM_CLASSES (256) +#define MAX_DOWN_SIZE (1000) + +#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } +inline void gpuAssert(cudaError_t code, const char* file, int line, bool abort = true) +{ + if (code != cudaSuccess) + { + fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); + if (abort) exit(code); + } +} + +clock_tick start_timer() { + return (high_resolution_clock::now()); +} + +void end_timer(clock_tick t1, const char msg[]) { + if (debug == 1) { + clock_tick t2 = high_resolution_clock::now(); + auto duration = duration_cast<milliseconds>(t2 - t1).count(); + printf("%s: %ld(ms)\n", msg, duration); + } +} + +//float cam_K[9] = {518.8579f, 0.0f, (float)frame_width / 2.0f, 0.0f, 518.8579f, (float)frame_height / 2.0f, 0.0f, 0.0f, 1.0f}; + + + + +void setup_CPP(int device, int num_threads, float v_unit, float v_margin, + float focal_length, float s_w, float s_h, + int vox_x, int vox_y, int vox_z, + int debug_flag, + /////////////////////////////////////////////////////////////////////////////////// + float cam_height, float cam_back + /////////////////////////////////////////////////////////////////////////////////// +) { + DEVICE = device; + NUM_THREADS = num_threads; + vox_unit = v_unit; + vox_margin = v_margin; + f = focal_length; + sensor_w = s_w; + sensor_h = s_h; + vox_size_x = vox_x; + vox_size_y = vox_y; + vox_size_z = vox_z; + cam_height_ = cam_height; + cam_back_ = cam_back; + + cudaDeviceProp deviceProperties; + cudaGetDeviceProperties(&deviceProperties, DEVICE); + cudaSetDevice(DEVICE); + + if (debug_flag == 1) { + + printf("\nUsing GPU: %s - (device %d)\n", deviceProperties.name, DEVICE); + printf("Total Memory: %ld\n", deviceProperties.totalGlobalMem); + printf("Max threads per block: %d\n", deviceProperties.maxThreadsPerBlock); + printf("Max threads dimension: (%d, %d, %d)\n", deviceProperties.maxGridSize[0], + deviceProperties.maxGridSize[1], + deviceProperties.maxGridSize[2]); + printf("Major, Minor: (%d, %d)\n", deviceProperties.major, deviceProperties.minor); + printf("Multiprocessor count: %d\n", deviceProperties.multiProcessorCount); + printf("Threads per block: %d\n", NUM_THREADS); + } + + debug = debug_flag; + + if (NUM_THREADS > deviceProperties.maxThreadsPerBlock) { + printf("Selected NUM_THREADS (%d) is greater than device's max threads per block (%d)\n", + NUM_THREADS, deviceProperties.maxThreadsPerBlock); + exit(0); + } + + + float parameters[10]; + + cudaMalloc(¶meters_GPU, 10 * sizeof(float)); + + parameters[VOX_UNIT] = vox_unit; + parameters[VOX_MARGIN] = vox_margin; + parameters[CAM_F] = f; + parameters[SENSOR_W] = sensor_w; + parameters[SENSOR_H] = sensor_h; + parameters[VOX_SIZE_X] = (float)vox_size_x; + parameters[VOX_SIZE_Y] = (float)vox_size_y; + parameters[VOX_SIZE_Z] = (float)vox_size_z; + parameters[CAM_HEIGHT] = cam_height_; + parameters[GO_BACK] = cam_back_; + cudaMemcpy(parameters_GPU, parameters, 10 * sizeof(float), cudaMemcpyHostToDevice); + + +} + +void clear_parameters_GPU() { + cudaFree(parameters_GPU); +} + + +__global__ +void point_cloud_kernel(float* baseline, unsigned char* depth_data, + float* point_cloud, int* width, int* height) { + + //Rerieve pixel coodinates + int pixel_idx = threadIdx.x + blockIdx.x * blockDim.x; + + if (pixel_idx >= (*width * *height)) + return; + + int pixel_y = pixel_idx / *width; + int pixel_x = pixel_idx % *width; + + float CV_PI = 3.141592; + + int max_radius = 30; + int inf_border = 160; // Range (in pixel) from the pole to exclude from point cloud generation + double unit_h, unit_w; //angular size of 1 pixel + float disp_scale = 2; + float disp_offset = -120; + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + // Get point in world coordinate + int point_disparity = depth_data[pixel_y * *width + pixel_x]; + + + float longitude, latitude, radius, angle_disp; + + latitude = pixel_y * unit_h * CV_PI; + + longitude = pixel_x * unit_w * CV_PI; + + point_cloud[6 * pixel_idx + 3] = latitude; + point_cloud[6 * pixel_idx + 4] = longitude; + + if (point_disparity == 0) + return; + + if (pixel_y<inf_border || pixel_y> *height - inf_border) + return; + + angle_disp = (point_disparity / disp_scale + disp_offset) * unit_h * CV_PI; + + if (latitude + angle_disp < 0) + angle_disp = 0.01; + + if (angle_disp == 0) { + radius = max_radius; + point_disparity = 0; + } + else + radius = *baseline / ((sin(latitude) / tan(latitude + angle_disp)) - cos(latitude)); + + if (radius > max_radius || radius < 0.0) { + radius = max_radius; + point_disparity = 0; + } + + // spherical to cartesian coordinate + float rx = radius * sin(latitude) * cos(CV_PI - longitude); + float rz = radius * sin(latitude) * sin(CV_PI - longitude); + float ry = radius * cos(latitude); / + + + point_cloud[6 * pixel_idx + 0] = rx; + point_cloud[6 * pixel_idx + 1] = ry; + point_cloud[6 * pixel_idx + 2] = rz; + point_cloud[6 * pixel_idx + 5] = radius; + +} + +__global__ +void point_cloud_stanford_kernel(uint16_t* depth_data, + float* point_cloud, int* width, int* height) { + + //Rerieve pixel coodinates + int pixel_idx = threadIdx.x + blockIdx.x * blockDim.x; + + if (pixel_idx >= (*width * *height)) + return; + + int pixel_y = pixel_idx / *width; + int pixel_x = pixel_idx % *width; + + float CV_PI = 3.141592; + + int max_radius = 30; + + double unit_h, unit_w; //angular size of 1 pixel + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + // Get point in world coordinate + // Try to parallel later + + uint16_t point_depth = depth_data[pixel_y * *width + pixel_x]; + + + float longitude, latitude, radius; + + latitude = pixel_y * unit_h * CV_PI; + + longitude = pixel_x * unit_w * CV_PI; + + point_cloud[6 * pixel_idx + 3] = latitude; + point_cloud[6 * pixel_idx + 4] = longitude; + + if (point_depth == 65535) + return; + + radius = point_depth / 512.0; + + if (radius > max_radius || radius < 0.0) { + radius = max_radius; + point_depth = 0; + } + + float rx = radius * sin(latitude) * cos(CV_PI - longitude); + float rz = radius * sin(latitude) * sin(CV_PI - longitude); + float ry = radius * cos(latitude); //+.20cm to get the floor + + point_cloud[6 * pixel_idx + 0] = rx; + point_cloud[6 * pixel_idx + 1] = ry; + point_cloud[6 * pixel_idx + 2] = rz; + point_cloud[6 * pixel_idx + 5] = radius; + +} + + + + + +void get_point_cloud_CPP(float baseline, unsigned char* depth_data, float* point_cloud, int width, int height) { + + clock_tick t1 = start_timer(); + + float* baseline_GPU; + int* width_GPU; + int* height_GPU; + unsigned char* depth_data_GPU; + float* point_cloud_GPU; + int num_pixels = width * height; + + + gpuErrchk(cudaMalloc(&baseline_GPU, sizeof(float))); + gpuErrchk(cudaMalloc(&width_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&height_GPU, sizeof(int))); + + gpuErrchk(cudaMalloc(&depth_data_GPU, num_pixels * sizeof(unsigned char))); + gpuErrchk(cudaMalloc(&point_cloud_GPU, 6 * num_pixels * sizeof(float))); + gpuErrchk(cudaMemset(point_cloud_GPU, 0, 6 * num_pixels * sizeof(float))); + + + gpuErrchk(cudaMemcpy(baseline_GPU, &baseline, sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(width_GPU, &width, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(height_GPU, &height, sizeof(int), cudaMemcpyHostToDevice)); + + + gpuErrchk(cudaMemcpy(depth_data_GPU, depth_data, height * width * sizeof(unsigned char), cudaMemcpyHostToDevice)); + + end_timer(t1, "Prepare duration"); + + if (debug == 1) printf("frame width: %d frame heigth: %d num_pixels %d\n", width, height, num_pixels); + + + t1 = start_timer(); + + int NUM_BLOCKS = int((width * height + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + if (debug == 1) printf("NUM_BLOCKS: %d NUM_THREADS: %d\n", NUM_BLOCKS, NUM_THREADS); + + point_cloud_kernel << <NUM_BLOCKS, NUM_THREADS >> > (baseline_GPU, depth_data_GPU, point_cloud_GPU, + width_GPU, height_GPU); + + gpuErrchk(cudaPeekAtLastError()); + + gpuErrchk(cudaDeviceSynchronize()); + + end_timer(t1, "depth2Grid duration"); + + cudaMemcpy(point_cloud, point_cloud_GPU, 6 * num_pixels * sizeof(float), cudaMemcpyDeviceToHost); + + cudaFree(baseline_GPU); + cudaFree(width_GPU); + cudaFree(height_GPU); + cudaFree(depth_data_GPU); + cudaFree(point_cloud_GPU); + + end_timer(t1, "closeup duration"); + +} + +void get_point_cloud_stanford_CPP(uint16_t* depth_data, float* point_cloud, int width, int height) { + + clock_tick t1 = start_timer(); + + int* width_GPU; + int* height_GPU; + uint16_t* depth_data_GPU; + float* point_cloud_GPU; + + int num_pixels = width * height; + + + gpuErrchk(cudaMalloc(&width_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&height_GPU, sizeof(int))); + + gpuErrchk(cudaMalloc(&depth_data_GPU, num_pixels * sizeof(uint16_t))); + gpuErrchk(cudaMalloc(&point_cloud_GPU, 6 * num_pixels * sizeof(float))); + gpuErrchk(cudaMemset(point_cloud_GPU, 0, 6 * num_pixels * sizeof(float))); + + gpuErrchk(cudaMemcpy(width_GPU, &width, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(height_GPU, &height, sizeof(int), cudaMemcpyHostToDevice)); + + gpuErrchk(cudaMemcpy(depth_data_GPU, depth_data, height * width * sizeof(uint16_t), cudaMemcpyHostToDevice)); + + end_timer(t1, "Prepare duration"); + + if (debug == 1) printf("frame width: %d frame heigth: %d num_pixels %d\n", width, height, num_pixels); + + + t1 = start_timer(); + + int NUM_BLOCKS = int((width * height + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + if (debug == 1) printf("NUM_BLOCKS: %d NUM_THREADS: %d\n", NUM_BLOCKS, NUM_THREADS); + + point_cloud_stanford_kernel << <NUM_BLOCKS, NUM_THREADS >> > (depth_data_GPU, point_cloud_GPU, + width_GPU, height_GPU); + + gpuErrchk(cudaPeekAtLastError()); + + gpuErrchk(cudaDeviceSynchronize()); + + end_timer(t1, "depth2Grid duration"); + + cudaMemcpy(point_cloud, point_cloud_GPU, 6 * num_pixels * sizeof(float), cudaMemcpyDeviceToHost); + + cudaFree(width_GPU); + cudaFree(height_GPU); + cudaFree(depth_data_GPU); + cudaFree(point_cloud_GPU); + + end_timer(t1, "closeup duration"); + +} + + +__global__ +void get_voxels_kernel(unsigned char* depth_data_GPU, float* point_cloud_GPU, int* point_cloud_size_GPU, + float* boundaries_GPU, int* vol_number_GPU, unsigned char* vox_grid_GPU, float* parameters_GPU) { + + float vox_unit_GPU = parameters_GPU[VOX_UNIT]; + float sensor_w_GPU = parameters_GPU[SENSOR_W]; + float sensor_h_GPU = parameters_GPU[SENSOR_H]; + float f_GPU = parameters_GPU[CAM_F]; + int vox_size_x_GPU = (int)parameters_GPU[VOX_SIZE_X]; + int vox_size_y_GPU = (int)parameters_GPU[VOX_SIZE_Y]; + int vox_size_z_GPU = (int)parameters_GPU[VOX_SIZE_Z]; + + float cam_hight_GPU = parameters_GPU[CAM_HEIGHT]; + float go_back_GPU = parameters_GPU[GO_BACK]; + //Rerieve pixel coodinates + int point_idx = threadIdx.x + blockIdx.x * blockDim.x; + + if (point_idx >= *point_cloud_size_GPU) + return; + + int x_idx = point_idx * 6 + 0; + int y_idx = point_idx * 6 + 1; + int z_idx = point_idx * 6 + 2; + int lat_idx = point_idx * 6 + 3; + int long_idx = point_idx * 6 + 4; + int rd_idx = point_idx * 6 + 5; + + float min_x = boundaries_GPU[0]; + float max_x = boundaries_GPU[1]; + float min_y = boundaries_GPU[2]; + float max_y = boundaries_GPU[3]; + float min_z = boundaries_GPU[4]; + float max_z = boundaries_GPU[5]; + + float wx = point_cloud_GPU[x_idx]; + float wy = point_cloud_GPU[y_idx]; + float wz = point_cloud_GPU[z_idx]; + float latitude = point_cloud_GPU[lat_idx]; + float longitude = point_cloud_GPU[long_idx]; + float rd = point_cloud_GPU[rd_idx]; + + if ((wx == 0.) && (wy == 0.) && (wz == 0.)) { + return; + } + + + if ((wx < min_x) || (wx > max_x) || (wy < min_y) || (wy > max_y) || (wz < min_z) || (wz > max_z)) { + return; + } + + + int vx, vy, vz; + + //Adjust to vol_number + if (*vol_number_GPU == 1) { // Front view ==> rotate 90 + + + float rotated_wx = wz; // Swap wx and wz to simulate a 90-degree rotation + float rotated_wz = -wx; + + float angle_dev_h = (abs(rotated_wz) + abs(rd)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(rotated_wz) + abs(rd)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(rotated_wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + return; + } + + vz = (int)floor(rotated_wz / vox_unit_GPU); + vx = (int)floor(rotated_wx / vox_unit_GPU + vox_size_z_GPU / 2); + vy = (int)floor((wy - (min_y - FLOOR_OFFSET)) / vox_unit_GPU); + + } + + if (*vol_number_GPU == 2) { // Left view ==>180 degree (phi) + + //Calculating viewing angle deviation for each point + float angle_dev_h = (abs(wz) + abs(rd)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(wz) + abs(rd)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + + return; + } + + //voxel coordinates + vz = (int)floor(wz / vox_unit_GPU); + vx = (int)floor(wx / vox_unit_GPU + vox_size_z_GPU / 2); + vy = (int)floor((wy - (min_y - FLOOR_OFFSET)) / vox_unit_GPU); + + } + + if (*vol_number_GPU == 3) { // Back view ==> 270 degree rotation (3phi/2) + + float rotated_wx = -wz; // Swap wx and wz to simulate the rotation + float rotated_wz = wx; + + + float angle_dev_h = (abs(rotated_wz) + abs(rd)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(rotated_wz) + abs(rd)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(rotated_wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + return; + } + + vz = (int)floor(rotated_wz / vox_unit_GPU); + vx = (int)floor(rotated_wx / vox_unit_GPU + vox_size_z_GPU / 2); + vy = (int)floor((wy - (min_y - FLOOR_OFFSET)) / vox_unit_GPU); + + } + + if (*vol_number_GPU == 4) { // Right view ==> 0 degree + + float angle_dev_h = (abs(-wz) + abs(rd)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(-wz) + abs(rd)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(-wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + return; + } + + vz = (int)floor(-wz / vox_unit_GPU); + vx = (int)floor(-wx / vox_unit_GPU + vox_size_z_GPU / 2); + vy = (int)floor((wy - (min_y - FLOOR_OFFSET)) / vox_unit_GPU); + + } + if (vx >= 0 && vx < vox_size_x_GPU && vy >= 0 && vy < vox_size_y_GPU && vz >= 0 && vz < vox_size_z_GPU) { + int vox_idx = vz * vox_size_x_GPU * vox_size_y_GPU + vy * vox_size_x_GPU + vx; + vox_grid_GPU[vox_idx] = float(1.0); + } + +} + +__global__ +void get_depth_mapping_idx_kernel(unsigned char* vox_grid_GPU, float* depth_mapping_3d_GPU, float* parameters_GPU) +{ + // conver from image corrdinate (point_depth) --> camera coordinate (point_cam) --> world coordinate (point_base) + float sensor_w_GPU = parameters_GPU[SENSOR_W]; + float sensor_h_GPU = parameters_GPU[SENSOR_H]; + int vox_size_x_GPU = (int)parameters_GPU[VOX_SIZE_X]; + int vox_size_y_GPU = (int)parameters_GPU[VOX_SIZE_Y]; + int vox_size_z_GPU = (int)parameters_GPU[VOX_SIZE_Z]; + + int x = blockIdx.x * blockDim.x + threadIdx.x; + int y = blockIdx.y * blockDim.y + threadIdx.y; + int z = blockIdx.z * blockDim.z + threadIdx.z; + if (x >= 0 && x < vox_size_x_GPU && y >= 0 && y < vox_size_y_GPU && z >= 0 && z < vox_size_z_GPU) { + int vox_idx = z * vox_size_x_GPU * vox_size_y_GPU + y * vox_size_x_GPU + x; + if (vox_grid_GPU[vox_idx] > 0 ) { + int pixel_x = x; // assuming x maps directly to pixel_x + int pixel_y = y; // assuming y maps directly to pixel_y + if (pixel_x < int(sensor_w_GPU)&& pixel_y < int(sensor_h_GPU)) { + depth_mapping_3d_GPU[pixel_y * int(sensor_w_GPU) + pixel_x] = vox_idx; + } + } + } + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void get_voxels_CPP( + ///////////////////// + unsigned char* depth_data, + ///////////////////// + float* point_cloud, int width, int height, float* boundaries, int vol_number, + unsigned char* vox_grid, +///////////////////// +float* depth_mapping +//////////////////// +) { + + clock_tick t1 = start_timer(); + + int point_cloud_size = width * height; + + float* point_cloud_GPU; + int* point_cloud_size_GPU; + float* boundaries_GPU; + int* vol_number_GPU; + unsigned char* vox_grid_GPU; + ///////////////////////////////////////// + float* depth_mapping_3d_GPU; + unsigned char* depth_data_GPU; + //////////////////////////////////////// + + int num_voxels = vox_size_x * vox_size_y * vox_size_z; + + if (debug == 1) printf("get_voxels - point_cloud_size: %d vol_number: %d voxel_size: %d %d %d\n", + point_cloud_size, vol_number, vox_size_x, vox_size_y, vox_size_z); + + if (debug == 1) printf("get_voxels - boundaries: (%2.2f %2.2f) (%2.2f %2.2f) (%2.2f %2.2f)\n", + boundaries[0], boundaries[1], boundaries[2], boundaries[3], boundaries[4], boundaries[5]); + + + gpuErrchk(cudaMalloc(&point_cloud_GPU, point_cloud_size * 6 * sizeof(float))); + gpuErrchk(cudaMalloc(&point_cloud_size_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&boundaries_GPU, 6 * sizeof(float))); + gpuErrchk(cudaMalloc(&vol_number_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&vox_grid_GPU, num_voxels * sizeof(unsigned char))); + ///////////////////////////////////////////////////////////////////// + gpuErrchk(cudaMalloc(&depth_data_GPU, point_cloud_size * sizeof(unsigned char))); + gpuErrchk(cudaMalloc(&depth_mapping_3d_GPU, int(sensor_h) * int(sensor_w) * sizeof(float))); + ///////////////////////////////////////////////////////////////////// + + gpuErrchk(cudaMemcpy(point_cloud_GPU, point_cloud, point_cloud_size * 6 * sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(point_cloud_size_GPU, &point_cloud_size, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(boundaries_GPU, boundaries, 6 * sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(vol_number_GPU, &vol_number, sizeof(int), cudaMemcpyHostToDevice)); + + gpuErrchk(cudaMemset(vox_grid_GPU, 0, num_voxels * sizeof(unsigned char))); + + gpuErrchk(cudaMemcpy(depth_mapping_3d_GPU, depth_mapping, int(sensor_h) * int(sensor_w) * sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(depth_data_GPU, depth_data, point_cloud_size * sizeof(unsigned char), cudaMemcpyHostToDevice)); + + ////////////////////////////////////////////////////////////////// + end_timer(t1, "Prepare duration"); + + t1 = start_timer(); + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// test kernal/////////////////////////////////////////////////// + int NUM_BLOCKS = int((point_cloud_size + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + if (debug == 1) printf("get_voxels - NUM_BLOCKS: %d NUM_THREADS: %d\n", NUM_BLOCKS, NUM_THREADS); + + + get_voxels_kernel << <NUM_BLOCKS, NUM_THREADS >> > (depth_data_GPU, point_cloud_GPU, point_cloud_size_GPU, boundaries_GPU, vol_number_GPU, vox_grid_GPU, parameters_GPU); + + + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + dim3 threadsPerBlock(8, 8, 8); + dim3 numBlocks((vox_size_x + threadsPerBlock.x - 1) / threadsPerBlock.x, + (vox_size_y + threadsPerBlock.y - 1) / threadsPerBlock.y, + (vox_size_z + threadsPerBlock.z - 1) / threadsPerBlock.z); + get_depth_mapping_idx_kernel << <numBlocks, threadsPerBlock >> > (vox_grid_GPU, depth_mapping_3d_GPU, parameters_GPU); + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + end_timer(t1, "get_voxels duration"); + + + + cudaMemcpy(vox_grid, vox_grid_GPU, num_voxels * sizeof(unsigned char), cudaMemcpyDeviceToHost); + + /// ////////////////////////////////////////////////////////////////////////////////////////// + cudaMemcpy(depth_mapping, depth_mapping_3d_GPU, int(sensor_h) * int(sensor_w) * sizeof(float), cudaMemcpyDeviceToHost); + cudaMemcpy(depth_data, depth_data_GPU, point_cloud_size * sizeof(unsigned char), cudaMemcpyDeviceToHost); + /// ////////////////////////////////////////////////////////////////////////////////////////// + + cudaFree(point_cloud_GPU); + cudaFree(point_cloud_size_GPU); + cudaFree(boundaries_GPU); + cudaFree(vol_number_GPU); + cudaFree(vox_grid_GPU); + + //////////////////////////////////////// + cudaFree(depth_mapping_3d_GPU); + cudaFree(depth_data_GPU); + //////////////////////////////////////// + end_timer(t1, "cleanup duration"); + +} + +__global__ +void get_one_hot_kernel(float* point_cloud_GPU, int* point_cloud_size_GPU, + float* boundaries_GPU, int* one_hot_GPU, float* parameters_GPU) { + + //Rerieve pixel coodinates + int point_idx = threadIdx.x + blockIdx.x * blockDim.x; + if (point_idx >= *point_cloud_size_GPU) + return; + + + + float wx = point_cloud_GPU[point_idx * 4 + 0]; + float wy = point_cloud_GPU[point_idx * 4 + 1]; + float wz = point_cloud_GPU[point_idx * 4 + 2]; + float lbl = point_cloud_GPU[point_idx * 4 + 3]; + + float min_x = boundaries_GPU[0]; + float max_x = boundaries_GPU[1]; + float min_y = boundaries_GPU[2]; + float max_y = boundaries_GPU[3]; + float min_z = boundaries_GPU[4]; + float max_z = boundaries_GPU[5]; + + if ((wx < min_x) || (wx > max_x) || (wy < min_y) || (wy > max_y) || (wz < min_z) || (wz > max_z)) { + + return; + } + + + float vox_unit_GPU = parameters_GPU[VOX_UNIT] * 4; // downsampling here + + int vox_size_x_GPU = (int)(parameters_GPU[VOX_SIZE_X] / 2); + int vox_size_y_GPU = (int)(parameters_GPU[VOX_SIZE_Y] / 4); + int vox_size_z_GPU = (int)(parameters_GPU[VOX_SIZE_Z] / 2); + + int vx = (int)floor(wx / vox_unit_GPU) + vox_size_x_GPU / 2; + int vy = (int)floor((wy - min_y) / vox_unit_GPU); + int vz = (int)floor(wz / vox_unit_GPU) + vox_size_z_GPU / 2; + + if (vx >= 0 && vx < vox_size_x_GPU && vy >= 0 && vy < vox_size_y_GPU && vz >= 0 && vz < vox_size_z_GPU) { + int vox_idx = vz * vox_size_x_GPU * vox_size_y_GPU * 12 + vy * vox_size_x_GPU * 12 + vx * 12 + lbl; + + atomicAdd(&one_hot_GPU[vox_idx], 1); + + } + else { + + return; + } +} + + +__global__ +void get_gt_kernel(int* one_hot_GPU, unsigned char* gt_grid_GPU, float* parameters_GPU) { + + int vox_idx = threadIdx.x + blockIdx.x * blockDim.x; + + int vox_size_x_GPU = (int)(parameters_GPU[VOX_SIZE_X] / 2); + int vox_size_y_GPU = (int)(parameters_GPU[VOX_SIZE_Y] / 4); + int vox_size_z_GPU = (int)(parameters_GPU[VOX_SIZE_Z] / 2); + + if (vox_idx >= vox_size_x_GPU * vox_size_y_GPU * vox_size_z_GPU) { + return; + } + + + int z = (vox_idx / (vox_size_x_GPU * vox_size_y_GPU)) % vox_size_z_GPU; + int y = (vox_idx / vox_size_x_GPU) % vox_size_y_GPU; + int x = vox_idx % vox_size_x_GPU; + + + int lbl_count = 0; + int occup_count = 0; + unsigned char best_lbl = 0; + + for (int i = 0; i < 12; i++) { + occup_count += one_hot_GPU[vox_idx * 12 + i]; + if (one_hot_GPU[vox_idx * 12 + i] > lbl_count) { + lbl_count = one_hot_GPU[vox_idx * 12 + i]; + best_lbl = i; + } + + } + + if (occup_count > 32) { //reduce noise + gt_grid_GPU[vox_idx] = best_lbl; + } + +} + + + +void get_gt_CPP(float* point_cloud, int point_cloud_size, float* boundaries, unsigned char* gt_grid) { + + clock_tick t1 = start_timer(); + + float* point_cloud_GPU; + int* point_cloud_size_GPU; + float* boundaries_GPU; + int* one_hot_grid_GPU; + unsigned char* gt_grid_GPU; + + int num_voxels = vox_size_x / 2 * vox_size_y / 4 * vox_size_z / 2; + + if (debug == 1) printf("get_gt - point_cloud_size: %d voxel_size: %d %d %d\n", + point_cloud_size, vox_size_x / 2, vox_size_y / 4, vox_size_z / 2); + + if (debug == 1) printf("get_gt - boundaries: (%2.2f %2.2f) (%2.2f %2.2f) (%2.2f %2.2f)\n", + boundaries[0], boundaries[1], boundaries[2], boundaries[3], boundaries[4], boundaries[5]); + + if (debug == 1) printf("(x %2.2f y %2.2f z %2.2f l %2.2f\n", + point_cloud[0], point_cloud[1], point_cloud[2], point_cloud[3]); + + + + gpuErrchk(cudaMalloc(&point_cloud_GPU, point_cloud_size * 4 * sizeof(float))); + gpuErrchk(cudaMalloc(&point_cloud_size_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&boundaries_GPU, 6 * sizeof(float))); + gpuErrchk(cudaMalloc(&one_hot_grid_GPU, num_voxels * 12 * sizeof(int))); + gpuErrchk(cudaMalloc(>_grid_GPU, num_voxels * sizeof(unsigned char))); + + gpuErrchk(cudaMemcpy(point_cloud_GPU, point_cloud, point_cloud_size * 4 * sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(point_cloud_size_GPU, &point_cloud_size, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(boundaries_GPU, boundaries, 6 * sizeof(float), cudaMemcpyHostToDevice)); + + gpuErrchk(cudaMemset(gt_grid_GPU, 0, num_voxels * sizeof(unsigned char))); + gpuErrchk(cudaMemset(one_hot_grid_GPU, 0, num_voxels * 12 * sizeof(int))); + + + end_timer(t1, "Prepare duration"); + + t1 = start_timer(); + int NUM_BLOCKS = int((point_cloud_size + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + if (debug == 1) printf("get_one_hot - NUM_BLOCKS: %d NUM_THREADS: %d\n", NUM_BLOCKS, NUM_THREADS); + + get_one_hot_kernel << <NUM_BLOCKS, NUM_THREADS >> > (point_cloud_GPU, point_cloud_size_GPU, + boundaries_GPU, one_hot_grid_GPU, parameters_GPU); + + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + NUM_BLOCKS = int((num_voxels + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + if (debug == 1) printf("get_gt - NUM_BLOCKS: %d NUM_THREADS: %d\n", NUM_BLOCKS, NUM_THREADS); + + get_gt_kernel << <NUM_BLOCKS, NUM_THREADS >> > (one_hot_grid_GPU, gt_grid_GPU, parameters_GPU); + + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + + end_timer(t1, "get_gt duration"); + + cudaMemcpy(gt_grid, gt_grid_GPU, num_voxels * sizeof(unsigned char), cudaMemcpyDeviceToHost); + + cudaFree(point_cloud_GPU); + cudaFree(point_cloud_size_GPU); + cudaFree(boundaries_GPU); + cudaFree(one_hot_grid_GPU); + cudaFree(gt_grid_GPU); + + end_timer(t1, "cleanup duration"); + +} + + +__global__ +void downsample_grid_kernel(unsigned char* in_grid_GPU, unsigned char* out_grid_GPU, float* parameters_GPU) { + + int vox_idx = threadIdx.x + blockIdx.x * blockDim.x; + float downscale = 4; + + int in_vox_size_x = (int)parameters_GPU[VOX_SIZE_X]; + int in_vox_size_y = (int)parameters_GPU[VOX_SIZE_Y]; + int in_vox_size_z = (int)parameters_GPU[VOX_SIZE_Z]; + int out_vox_size_x = (int)in_vox_size_x / downscale; + int out_vox_size_y = (int)in_vox_size_y / downscale; + int out_vox_size_z = (int)in_vox_size_z / downscale; + + if (vox_idx >= out_vox_size_x * out_vox_size_y * out_vox_size_z) { + return; + } + + int z = (vox_idx / (out_vox_size_x * out_vox_size_y)) % out_vox_size_z; + int y = (vox_idx / out_vox_size_x) % out_vox_size_y; + int x = vox_idx % out_vox_size_x; + + int sum_occupied = 0; + + for (int tmp_x = x * downscale; tmp_x < (x + 1) * downscale; ++tmp_x) { + for (int tmp_y = y * downscale; tmp_y < (y + 1) * downscale; ++tmp_y) { + for (int tmp_z = z * downscale; tmp_z < (z + 1) * downscale; ++tmp_z) { + + int tmp_vox_idx = tmp_z * in_vox_size_x * in_vox_size_y + tmp_y * in_vox_size_z + tmp_x; + + if (in_grid_GPU[tmp_vox_idx] > 0) { + sum_occupied += 1; + } + } + } + } + if (sum_occupied >= 4) { //empty threshold + out_grid_GPU[vox_idx] = 1; + } + else { + out_grid_GPU[vox_idx] = 0; + } + +} + +__global__ +void downsample_limits_kernel(unsigned char* in_grid_GPU, unsigned char* out_grid_GPU, float* parameters_GPU) { + + int vox_idx = threadIdx.x + blockIdx.x * blockDim.x; + float downscale = 4; + + int in_vox_size_x = (int)parameters_GPU[VOX_SIZE_X]; + int in_vox_size_y = (int)parameters_GPU[VOX_SIZE_Y]; + int in_vox_size_z = (int)parameters_GPU[VOX_SIZE_Z]; + int out_vox_size_x = (int)in_vox_size_x / downscale; + int out_vox_size_y = (int)in_vox_size_y / downscale; + int out_vox_size_z = (int)in_vox_size_z / downscale; + + if (vox_idx >= out_vox_size_x * out_vox_size_y * out_vox_size_z) { + return; + } + + int z = (vox_idx / (out_vox_size_x * out_vox_size_y)) % out_vox_size_z; + int y = (vox_idx / out_vox_size_x) % out_vox_size_y; + int x = vox_idx % out_vox_size_x; + + int sum_occupied = 0; + int sum_occluded = 0; + + for (int tmp_x = x * downscale; tmp_x < (x + 1) * downscale; ++tmp_x) { + for (int tmp_y = y * downscale; tmp_y < (y + 1) * downscale; ++tmp_y) { + for (int tmp_z = z * downscale; tmp_z < (z + 1) * downscale; ++tmp_z) { + + int tmp_vox_idx = tmp_z * in_vox_size_x * in_vox_size_y + tmp_y * in_vox_size_z + tmp_x; + + if (in_grid_GPU[tmp_vox_idx] == OCCUPIED) { + sum_occupied += 1; + } + if (in_grid_GPU[tmp_vox_idx] == OCCLUDED) { + sum_occluded += 1; + } + } + } + } + if (sum_occupied + sum_occluded >= 4) { //empty threshold + out_grid_GPU[vox_idx] = 1; + } + else { + out_grid_GPU[vox_idx] = 0; + } + +} + + +void downsample_grid_CPP(unsigned char* vox_grid, unsigned char* vox_grid_down) { + + clock_tick t1 = start_timer(); + + unsigned char* vox_grid_GPU; + unsigned char* vox_grid_down_GPU; + + int num_voxels = vox_size_x * vox_size_y * vox_size_z; + int num_voxels_down = num_voxels / 64; + + gpuErrchk(cudaMalloc(&vox_grid_GPU, num_voxels * sizeof(unsigned char))); + gpuErrchk(cudaMalloc(&vox_grid_down_GPU, num_voxels_down * sizeof(unsigned char))); + + gpuErrchk(cudaMemcpy(vox_grid_GPU, vox_grid, num_voxels * sizeof(unsigned char), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemset(vox_grid_down_GPU, 0, num_voxels_down * sizeof(unsigned char))); + + + end_timer(t1, "Prepare duration"); + + t1 = start_timer(); + int NUM_BLOCKS = int((num_voxels_down + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + if (debug == 1) printf("downsample - NUM_BLOCKS: %d NUM_THREADS: %d\n", NUM_BLOCKS, NUM_THREADS); + + downsample_grid_kernel << <NUM_BLOCKS, NUM_THREADS >> > (vox_grid_GPU, vox_grid_down_GPU, parameters_GPU); + + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + + end_timer(t1, "downsample duration"); + + cudaMemcpy(vox_grid_down, vox_grid_down_GPU, num_voxels_down * sizeof(unsigned char), cudaMemcpyDeviceToHost); + + cudaFree(vox_grid_GPU); + cudaFree(vox_grid_down_GPU); + + end_timer(t1, "cleanup duration"); + +} + + +void downsample_limits_CPP(unsigned char* vox_grid, unsigned char* vox_grid_down) { + + clock_tick t1 = start_timer(); + + unsigned char* vox_grid_GPU; + unsigned char* vox_grid_down_GPU; + + int num_voxels = vox_size_x * vox_size_y * vox_size_z; + int num_voxels_down = num_voxels / 64; + + gpuErrchk(cudaMalloc(&vox_grid_GPU, num_voxels * sizeof(unsigned char))); + gpuErrchk(cudaMalloc(&vox_grid_down_GPU, num_voxels_down * sizeof(unsigned char))); + + gpuErrchk(cudaMemcpy(vox_grid_GPU, vox_grid, num_voxels * sizeof(unsigned char), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemset(vox_grid_down_GPU, 0, num_voxels_down * sizeof(unsigned char))); + + + end_timer(t1, "Prepare duration"); + + t1 = start_timer(); + int NUM_BLOCKS = int((num_voxels_down + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + if (debug == 1) printf("downsample - NUM_BLOCKS: %d NUM_THREADS: %d\n", NUM_BLOCKS, NUM_THREADS); + + downsample_limits_kernel << <NUM_BLOCKS, NUM_THREADS >> > (vox_grid_GPU, vox_grid_down_GPU, parameters_GPU); + + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + + end_timer(t1, "downsample duration"); + + cudaMemcpy(vox_grid_down, vox_grid_down_GPU, num_voxels_down * sizeof(unsigned char), cudaMemcpyDeviceToHost); + + cudaFree(vox_grid_GPU); + cudaFree(vox_grid_down_GPU); + + end_timer(t1, "cleanup duration"); + +} + +__global__ + +void SquaredDistanceTransform(unsigned char* depth_data, unsigned char* vox_grid, + float* vox_tsdf, unsigned char* vox_limits, float* baseline, + int* width, int* height, float* boundaries_GPU, int* vol_number_GPU, float* parameters_GPU) { + + float vox_unit_GPU = parameters_GPU[VOX_UNIT]; + float vox_margin_GPU = parameters_GPU[VOX_MARGIN]; + float sensor_w_GPU = parameters_GPU[SENSOR_W]; + float sensor_h_GPU = parameters_GPU[SENSOR_H]; + float f_GPU = parameters_GPU[CAM_F]; + float cam_hight_GPU = parameters_GPU[CAM_HEIGHT]; + float go_back_GPU = parameters_GPU[GO_BACK]; + + int vox_size_x_GPU = (int)parameters_GPU[VOX_SIZE_X]; + int vox_size_y_GPU = (int)parameters_GPU[VOX_SIZE_Y]; + int vox_size_z_GPU = (int)parameters_GPU[VOX_SIZE_Z]; + + float min_x = boundaries_GPU[0]; + float max_x = boundaries_GPU[1]; + float min_y = boundaries_GPU[2]; + float max_y = boundaries_GPU[3]; + float min_z = boundaries_GPU[4]; + float max_z = boundaries_GPU[5]; + + //Rerieve pixel coodinates + int search_region = (int)roundf(vox_margin_GPU / vox_unit_GPU); + + int vox_idx = threadIdx.x + blockIdx.x * blockDim.x; + + if (vox_idx >= vox_size_x_GPU * vox_size_y_GPU * vox_size_z_GPU) { + return; + } + + + int z = (vox_idx / (vox_size_x_GPU * vox_size_y_GPU)) % vox_size_z_GPU; + int y = (vox_idx / vox_size_x_GPU) % vox_size_y_GPU; + int x = vox_idx % vox_size_x_GPU; + + // Get point in world coordinates + float wz; + float wx; + float wy; + + //Adjust to vol_number + if (*vol_number_GPU == 1) { // Front view + + wx = - (float(z)*vox_unit_GPU); + wz = (float(x) - (vox_size_x_GPU / 2)) *vox_unit_GPU ; + wy = float(y) * vox_unit_GPU + (min_y-FLOOR_OFFSET); + + if (wx < min_x || wx > max_x || wy < min_y || wy > max_y || wz < min_z || wz > max_z ){ + // outside ROOM + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_ROOM; + return; + } + ////////////////////////////////////////////////////////////////////////////////// + float CV_PI = 3.141592; + float longitude, latitude, point_depth, angle_disp; + + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + + float teta1, teta2; + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + float disp_scale = 2; + float disp_offset = -120; + int max_radius = 30; + + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + + int point_disparity = depth_data[pixel_y * *width + pixel_x]; + if (point_disparity == 0) { // mising depth + vox_tsdf[vox_idx] = -1.0; + return; + } + + angle_disp = (point_disparity / disp_scale + disp_offset) * unit_h * CV_PI; + + if (latitude + angle_disp < 0) + angle_disp = 0.01; + + if (angle_disp == 0) { + point_depth = max_radius; + point_disparity = 0; + } + else + point_depth = *baseline / ((sin(latitude) / tan(latitude + angle_disp)) - cos(latitude)); + + if (point_depth > max_radius || point_depth < 0.0) { + point_depth = max_radius; + point_disparity = 0; + } + //} + + float vox_depth = hip2; + ///////////////////////////////////////////////////////////////////////////////// + + float angle_dev_h = (abs(-wx) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; //rotated_wx = wz;, rotated_wz = -wx + float angle_dev_v = (abs(-wx) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + if ((abs(wz) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ///////////////////////////////////////////////////////////////////////////////////////// + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + ////////////////////////////////////////////////////////////////////////////////////////// + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + if (*vol_number_GPU == 2) { // Left view ==> 180 degree (phi) + + wz = float(z) * vox_unit_GPU; //point_base[0] + wx = (float(x) - (vox_size_z_GPU/2)) * vox_unit_GPU; //point_base[1] + wy = float(y) * vox_unit_GPU + (min_y-FLOOR_OFFSET); //point_base[2] + + if (wx < min_x || wx > max_x || wy < min_y || wy > max_y || wz < min_z || wz > max_z ){ + // outside ROOM + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_ROOM; + return; + } + ////////////////////////////////////////////////////////////////////////////////// + float CV_PI = 3.141592; + float longitude, latitude, point_depth, angle_disp; + + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + + float teta1, teta2; + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + float disp_scale = 2; + float disp_offset = -120; + int max_radius = 30; + + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + int point_disparity = depth_data[pixel_y * *width + pixel_x]; + if (point_disparity == 0) { // mising depth + vox_tsdf[vox_idx] = -1.0; + return; + } + + angle_disp = (point_disparity / disp_scale + disp_offset) * unit_h * CV_PI; + + if (latitude + angle_disp < 0) + angle_disp = 0.01; + + if (angle_disp == 0) { + point_depth = max_radius; + point_disparity = 0; + } + else + point_depth = *baseline / ((sin(latitude) / tan(latitude + angle_disp)) - cos(latitude)); + + if (point_depth > max_radius || point_depth < 0.0) { + point_depth = max_radius; + point_disparity = 0; + } + //} + + float vox_depth = hip2; + ///////////////////////////////////////////////////////////////////////////////// + + float angle_dev_h = (abs(wz) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(wz) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + if ((abs(wx)>angle_dev_h) || (abs(wy - min_y - cam_hight_GPU)>angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ///////////////////////////////////////////////////////////////////////////////////////// + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + ////////////////////////////////////////////////////////////////////////////////////////// + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + if (*vol_number_GPU == 3) { // Back view + + wx = (float(z)) * vox_unit_GPU; + wz = -((float(x) - (vox_size_x_GPU / 2)) * vox_unit_GPU); + wy = float(y) * vox_unit_GPU + (min_y - FLOOR_OFFSET); + + float rotated_wx = -wz; // Swap wx and wz to simulate a 90-degree rotation + float rotated_wz = wx; + ////////////////////////////////////////////////////////////////////////////////// + float CV_PI = 3.141592; + float longitude, latitude, point_depth, angle_disp; + + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + + float teta1, teta2; + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + float disp_scale = 2; + float disp_offset = -120; + int max_radius = 30; + + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + int point_disparity = depth_data[pixel_y * *width + pixel_x]; + if (point_disparity == 0) { // mising depth + vox_tsdf[vox_idx] = -1.0; + return; + } + + angle_disp = (point_disparity / disp_scale + disp_offset) * unit_h * CV_PI; + + if (latitude + angle_disp < 0) + angle_disp = 0.01; + + if (angle_disp == 0) { + point_depth = max_radius; + point_disparity = 0; + } + else + point_depth = *baseline / ((sin(latitude) / tan(latitude + angle_disp)) - cos(latitude)); + + if (point_depth > max_radius || point_depth < 0.0) { + point_depth = max_radius; + point_disparity = 0; + } + //} + + float vox_depth = hip2; + ///////////////////////////////////////////////////////////////////////////////// + float angle_dev_h = (abs(rotated_wz) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(rotated_wz) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(rotated_wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ///////////////////////////////////////////////////////////////////////////////////////// + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + ////////////////////////////////////////////////////////////////////////////////////////// + + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + if (*vol_number_GPU == 4) { // Right view ==> 0 degree + + wz = (float(-z) * vox_unit_GPU); //point_base[0] + wx = -((float(x) - (vox_size_z_GPU / 2)) * vox_unit_GPU); //point_base[1] + wy = float(y) * vox_unit_GPU + (min_y - FLOOR_OFFSET); //point_base[2] + + if (wx < min_x || wx > max_x || wy < min_y || wy > max_y || wz < min_z || wz > max_z) { + // outside ROOM + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_ROOM; + return; + } + ////////////////////////////////////////////////////////////////////////////////// + float CV_PI = 3.141592; + float longitude, latitude, point_depth, angle_disp; + + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + + float teta1, teta2; + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + float disp_scale = 2; + float disp_offset = -120; + int max_radius = 30; + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + int point_disparity = depth_data[pixel_y * *width + pixel_x]; + if (point_disparity == 0) { // mising depth + vox_tsdf[vox_idx] = -1.0; + return; + } + + angle_disp = (point_disparity / disp_scale + disp_offset) * unit_h * CV_PI; + + if (latitude + angle_disp < 0) + angle_disp = 0.01; + + if (angle_disp == 0) { + point_depth = max_radius; + point_disparity = 0; + } + else + point_depth = *baseline / ((sin(latitude) / tan(latitude + angle_disp)) - cos(latitude)); + + if (point_depth > max_radius || point_depth < 0.0) { + point_depth = max_radius; + point_disparity = 0; + } + + float vox_depth = hip2; + + ////////////////////////////////////////////////////////////////////////////////////////// + + float angle_dev_h = (abs(-wz) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(-wz) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(-wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ////////////////////////////////////////////////////////////////////////////////////////// + + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + ////////////////////////////////////////////////////////////////////////////////////////// + } +} + +/// //////////////////////////////////////////////////////////////////////////////////////////////////////////////// Stanford TSDF //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +__global__ +void SquaredDistanceTransform_stanford(uint16_t*depth_data, unsigned char *vox_grid, + float *vox_tsdf, unsigned char *vox_limits, + int *width, int *height, float *boundaries_GPU, int *vol_number_GPU, float *parameters_GPU) { + + float vox_unit_GPU = parameters_GPU[VOX_UNIT]; + float vox_margin_GPU = parameters_GPU[VOX_MARGIN]; + float sensor_w_GPU = parameters_GPU[SENSOR_W]; + float sensor_h_GPU = parameters_GPU[SENSOR_H]; + float f_GPU = parameters_GPU[CAM_F]; + float cam_hight_GPU = parameters_GPU[CAM_HEIGHT]; + float go_back_GPU = parameters_GPU[GO_BACK]; + + int vox_size_x_GPU = (int)parameters_GPU[VOX_SIZE_X]; + int vox_size_y_GPU = (int)parameters_GPU[VOX_SIZE_Y]; + int vox_size_z_GPU = (int)parameters_GPU[VOX_SIZE_Z]; + + float min_x = boundaries_GPU[0]; + float max_x = boundaries_GPU[1]; + float min_y = boundaries_GPU[2]; + float max_y = boundaries_GPU[3]; + float min_z = boundaries_GPU[4]; + float max_z = boundaries_GPU[5]; + + //Rerieve pixel coodinates + int search_region = (int)roundf(vox_margin_GPU / vox_unit_GPU); + + int vox_idx = threadIdx.x + blockIdx.x * blockDim.x; + + if (vox_idx >= vox_size_x_GPU * vox_size_y_GPU * vox_size_z_GPU) { + return; + } + + + int z = (vox_idx / (vox_size_x_GPU * vox_size_y_GPU)) % vox_size_z_GPU; + int y = (vox_idx / vox_size_x_GPU) % vox_size_y_GPU; + int x = vox_idx % vox_size_x_GPU; + + // Get point in world coordinates + float wz; + float wx; + float wy; + + //Adjust to vol_number + if (*vol_number_GPU == 1) { // Front view + + wx = -(float(z) * vox_unit_GPU); + wz = (float(x) - (vox_size_x_GPU / 2)) * vox_unit_GPU; + wy = float(y) * vox_unit_GPU + (min_y - FLOOR_OFFSET); + + if (wx < min_x || wx > max_x || wy < min_y || wy > max_y || wz < min_z || wz > max_z) { + // outside ROOM + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_ROOM; + return; + } + ////////////////////////////////////////////////////////////////////////////////// + + float CV_PI = 3.141592; + float longitude, latitude, point_depth; + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + float teta1, teta2; + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + int max_radius = 30; + + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + point_depth = 0.0; + // ensure pixel_x and pixel_y are within bounds + if (pixel_y >= 0 && pixel_y < *height && pixel_x >= 0 && pixel_x < *width) { + + point_depth = depth_data[pixel_y * *width + pixel_x]; + if (point_depth == 65535.) { // mising depth + vox_limits[vox_idx] = OUT_OF_FOV; + vox_tsdf[vox_idx] = -1.0; + return; + } + + + //if (vox_grid[vox_idx] > 0) { + point_depth = point_depth / 512.; + //} + + if (point_depth > max_radius || point_depth < 0.0) { + vox_limits[vox_idx] = OUT_OF_FOV; + point_depth = max_radius; + } + + } + + float vox_depth = hip2; + + ///////////////////////////////////////////////////////////////////////////////// + + float angle_dev_h = (abs(-wx) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; //rotated_wx = wz;, rotated_wz = -wx + float angle_dev_v = (abs(-wx) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + if ((abs(wz) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ///////////////////////////////////////////////////////////////////////////////////////// + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + + + ////////////////////////////////////////////////////////////////////////////////////////// + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + if (*vol_number_GPU == 2) { // Left view ==> 180 degree (phi) + + wz = float(z) * vox_unit_GPU; //point_base[0] + wx = (float(x) - (vox_size_z_GPU / 2)) * vox_unit_GPU; //point_base[1] + wy = float(y) * vox_unit_GPU + (min_y - FLOOR_OFFSET); //point_base[2] + + if (wx < min_x || wx > max_x || wy < min_y || wy > max_y || wz < min_z || wz > max_z) { + // outside ROOM + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_ROOM; + return; + } + ////////////////////////////////////////////////////////////////////////////////// + float CV_PI = 3.141592; + float longitude, latitude, point_depth; + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + float teta1, teta2; + + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + int max_radius = 30; + + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + point_depth = 0.0; + // ensure pixel_x and pixel_y are within bounds + if (pixel_y >= 0 && pixel_y < *height && pixel_x >= 0 && pixel_x < *width) { + + point_depth = depth_data[pixel_y * *width + pixel_x]; + if (point_depth == 65535.) { // mising depth + vox_limits[vox_idx] = OUT_OF_FOV; + vox_tsdf[vox_idx] = -1.0; + + return; + } + + + + point_depth = point_depth / 512.; + + if (point_depth > max_radius || point_depth < 0.0) { + vox_limits[vox_idx] = OUT_OF_FOV; + point_depth = max_radius; + } + + } + + float vox_depth = hip2; + + ///////////////////////////////////////////////////////////////////////////////// + // Calculating viewing angle deviation for each point + + float angle_dev_h = (abs(wz) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(wz) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + if ((abs(wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ///////////////////////////////////////////////////////////////////////////////////////// + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////////////////// + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + if (*vol_number_GPU == 3) { // Back view + + wx = (float(z)) * vox_unit_GPU; + wz = -((float(x) - (vox_size_x_GPU / 2)) * vox_unit_GPU); + wy = float(y) * vox_unit_GPU + (min_y - FLOOR_OFFSET); + + float rotated_wx = -wz; // Swap wx and wz to simulate a 90-degree rotation + float rotated_wz = wx; + ////////////////////////////////////////////////////////////////////////////////// + float CV_PI = 3.141592; + float longitude, latitude, point_depth; + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + float teta1, teta2; + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + int max_radius = 30; + + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + point_depth = 0.0; + // ensure pixel_x and pixel_y are within bounds + if (pixel_y >= 0 && pixel_y < *height && pixel_x >= 0 && pixel_x < *width) { + + point_depth = depth_data[pixel_y * *width + pixel_x]; + if (point_depth == 65535.) { // mising depth + vox_limits[vox_idx] = OUT_OF_FOV; + vox_tsdf[vox_idx] = -1.0; + return; + } + + point_depth = point_depth / 512.; + + if (point_depth > max_radius || point_depth < 0.0) { + vox_limits[vox_idx] = OUT_OF_FOV; + point_depth = max_radius; + } + + } + + float vox_depth = hip2; + + ///////////////////////////////////////////////////////////////////////////////// + float angle_dev_h = (abs(rotated_wz) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(rotated_wz) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(rotated_wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ///////////////////////////////////////////////////////////////////////////////////////// + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + + ////////////////////////////////////////////////////////////////////////////////////////// + + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + if (*vol_number_GPU == 4) { // Right view ==> 0 degree + + wz = (float(-z) * vox_unit_GPU); //point_base[0] + wx = -((float(x) - (vox_size_z_GPU / 2)) * vox_unit_GPU); //point_base[1] + wy = float(y) * vox_unit_GPU + (min_y - FLOOR_OFFSET); //point_base[2] + + if (wx < min_x || wx > max_x || wy < min_y || wy > max_y || wz < min_z || wz > max_z) { + // outside ROOM + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_ROOM; + return; + } + ////////////////////////////////////////////////////////////////////////////////// + float CV_PI = 3.141592; + float longitude, latitude, point_depth; + float hip1 = sqrtf(wx * wx + wz * wz); + float hip2 = sqrtf(hip1 * hip1 + wy * wy); + float teta1, teta2; + + teta1 = asin(wy / hip2); + + latitude = CV_PI / 2 - teta1; + + //longitude = 3*CV_PI/2 - teta2; + if (wx < 0) + teta2 = asin(wz / hip1); + else + teta2 = CV_PI - asin(wz / hip1); + + longitude = teta2; + + float unit_h, unit_w; //angular size of 1 pixel + int max_radius = 30; + + + unit_h = 1.0 / (*height); + unit_w = 2.0 / (*width); + + int pixel_y = latitude / (unit_h * CV_PI); + int pixel_x = longitude / (unit_w * CV_PI); + + point_depth = 0.0; + // ensure pixel_x and pixel_y are within bounds + if (pixel_y >= 0 && pixel_y < *height && pixel_x >= 0 && pixel_x < *width) { + + point_depth = depth_data[pixel_y * *width + pixel_x]; + if (point_depth == 65535.) { // mising depth + vox_limits[vox_idx] = OUT_OF_FOV; + vox_tsdf[vox_idx] = -1.0; + + return; + } + + point_depth = point_depth / 512.; + + if (point_depth > max_radius || point_depth < 0.0) { + vox_limits[vox_idx] = OUT_OF_FOV; + point_depth = max_radius; + } + + } + + float vox_depth = hip2; + ////////////////////////////////////////////////////////////////////////////////////////// + + float angle_dev_h = (abs(-wz) + abs(point_depth)) * (sensor_w_GPU / 2) / f_GPU; + float angle_dev_v = (abs(-wz) + abs(point_depth)) * (sensor_h_GPU / 2) / f_GPU; + + + if ((abs(-wx) > angle_dev_h) || (abs(wy - min_y - cam_hight_GPU) > angle_dev_v)) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + ////////////////////////////////////////////////////////////////////////////////////////// + + if (wx == 0.0 && wy == 0 && wz == 0) { + vox_tsdf[vox_idx] = 2000.; + vox_limits[vox_idx] = OUT_OF_FOV; + return; + } + //OCCUPIED + if (vox_grid[vox_idx] > 0) { + vox_tsdf[vox_idx] = 0; + vox_limits[vox_idx] = OCCUPIED; + return; + } + + float sign; + if (abs(point_depth - vox_depth) < 0.001) { + sign = 1; // avoid NaN + } + else { + sign = (point_depth - vox_depth) / abs(point_depth - vox_depth); + } + vox_tsdf[vox_idx] = sign; + if (sign > 0.0) { + vox_limits[vox_idx] = EMPTY_VISIBLE; + } + else { + vox_limits[vox_idx] = OCCLUDED; + + } + + //compute the minimum TSDF value for the current voxel within the search region, considering the occupied voxels in the grid + for (int iix = max(0, x - search_region); iix < min((int)vox_size_x_GPU, x + search_region + 1); iix++) { + for (int iiy = max(0, y - search_region); iiy < min((int)vox_size_y_GPU, y + search_region + 1); iiy++) { + for (int iiz = max(0, z - search_region); iiz < min((int)vox_size_z_GPU, z + search_region + 1); iiz++) { + + int iidx = iiz * vox_size_x_GPU * vox_size_y_GPU + iiy * vox_size_x_GPU + iix; + if (vox_grid[iidx] > 0) { + + float xd = abs(x - iix); + float yd = abs(y - iiy); + float zd = abs(z - iiz); + float tsdf_value = sqrtf(xd * xd + yd * yd + zd * zd) / (float)search_region; + if (tsdf_value < abs(vox_tsdf[vox_idx])) { + vox_tsdf[vox_idx] = float(tsdf_value * sign); + } + } + } + } + } + ////////////////////////////////////////////////////////////////////////////////////////// + } + +} + +void FlipTSDF_CPP(float* vox_tsdf) { + + clock_tick t1 = start_timer(); + + for (int vox_idx = 0; vox_idx < vox_size_x * vox_size_y * vox_size_x; vox_idx++) { + + float value = float(vox_tsdf[vox_idx]); + if (value > 1) + value = 1; + + + float sign; + if (abs(value) < 0.001) + sign = 1; + else + sign = value / abs(value); + + vox_tsdf[vox_idx] = sign * (max(0.001, (1.0 - abs(value)))); + } + end_timer(t1, "FlipTSDF"); +} + + +void FTSDFDepth_CPP(unsigned char* depth_data, + unsigned char* vox_grid, + float* vox_tsdf, + unsigned char* vox_limits, + float baseline, + int width, + int height, + float* boundaries, + int vol_number) { + + clock_tick t1 = start_timer(); + + float* boundaries_GPU; + unsigned char* vox_grid_GPU; + + unsigned char* depth_data_GPU; + float* vox_tsdf_GPU; + + unsigned char* vox_limits_GPU; + float* baseline_GPU; + int* width_GPU; + int* height_GPU; + int* vol_number_GPU; + + int num_voxels = vox_size_x * vox_size_y * vox_size_z; + int num_pixels = width * height; // spherical image size + + if (debug == 1) printf("FTSDFDepth - boundaries: (%2.2f %2.2f) (%2.2f %2.2f) (%2.2f %2.2f)\n", + boundaries[0], boundaries[1], boundaries[2], boundaries[3], boundaries[4], boundaries[5]); + + + gpuErrchk(cudaMalloc(&boundaries_GPU, 6 * sizeof(float))); + gpuErrchk(cudaMalloc(&vox_grid_GPU, num_voxels * sizeof(unsigned char))); + + gpuErrchk(cudaMalloc(&depth_data_GPU, num_pixels * sizeof(unsigned char))); + gpuErrchk(cudaMalloc(&vox_tsdf_GPU, num_voxels * sizeof(float))); + + gpuErrchk(cudaMalloc(&vox_limits_GPU, num_voxels * sizeof(unsigned char))); + gpuErrchk(cudaMalloc(&baseline_GPU, sizeof(float))); + gpuErrchk(cudaMalloc(&width_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&height_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&vol_number_GPU, sizeof(int))); + + gpuErrchk(cudaMemcpy(boundaries_GPU, boundaries, 6 * sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(vox_grid_GPU, vox_grid, num_voxels * sizeof(unsigned char), cudaMemcpyHostToDevice)); + + gpuErrchk(cudaMemcpy(depth_data_GPU, depth_data, num_pixels * sizeof(unsigned char), cudaMemcpyHostToDevice)); + + + gpuErrchk(cudaMemcpy(baseline_GPU, &baseline, sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(width_GPU, &width, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(height_GPU, &height, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(vol_number_GPU, &vol_number, sizeof(int), cudaMemcpyHostToDevice)); + + gpuErrchk(cudaMemset(vox_limits_GPU, 0, num_voxels * sizeof(unsigned char))); + gpuErrchk(cudaMemset(vox_tsdf_GPU, 0, num_voxels * sizeof(float))); + + + + end_timer(t1, "Prepare duration"); + + t1 = start_timer(); + int NUM_BLOCKS = int((num_voxels + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + + SquaredDistanceTransform << <NUM_BLOCKS, NUM_THREADS >> > (depth_data_GPU, vox_grid_GPU, vox_tsdf_GPU, vox_limits_GPU, baseline_GPU, width_GPU, height_GPU, boundaries_GPU, vol_number_GPU, parameters_GPU); + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + end_timer(t1, "SquaredDistanceTransform duration"); + cudaMemcpy(vox_tsdf, vox_tsdf_GPU, num_voxels * sizeof(float), cudaMemcpyDeviceToHost); + + cudaMemcpy(vox_limits, vox_limits_GPU, num_voxels * sizeof(unsigned char), cudaMemcpyDeviceToHost); + + cudaFree(boundaries_GPU); + cudaFree(vox_grid_GPU); + cudaFree(depth_data_GPU); + cudaFree(vox_tsdf_GPU); + cudaFree(vox_limits_GPU); + cudaFree(baseline_GPU); + cudaFree(width_GPU); + cudaFree(height_GPU); + cudaFree(vol_number_GPU); + + end_timer(t1, "cleanup duration"); + + FlipTSDF_CPP(vox_tsdf); + +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////// Stanford /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void FTSDFDepth_stanford_CPP(uint16_t* depth_data, + unsigned char* vox_grid, + + float* vox_tsdf, + + unsigned char* vox_limits, + int width, + int height, + float* boundaries, + int vol_number) { + + clock_tick t1 = start_timer(); + + float* boundaries_GPU; + unsigned char* vox_grid_GPU; + + uint16_t* depth_data_GPU; + float* vox_tsdf_GPU; + + unsigned char* vox_limits_GPU; + int* width_GPU; + int* height_GPU; + int* vol_number_GPU; + + int num_voxels = vox_size_x * vox_size_y * vox_size_z; + int num_pixels = width * height; + + if (debug == 1) printf("FTSDFDepth - boundaries: (%2.2f %2.2f) (%2.2f %2.2f) (%2.2f %2.2f)\n", + boundaries[0], boundaries[1], boundaries[2], boundaries[3], boundaries[4], boundaries[5]); + + gpuErrchk(cudaMalloc(&boundaries_GPU, 6 * sizeof(float))); + gpuErrchk(cudaMalloc(&vox_grid_GPU, num_voxels * sizeof(unsigned char))); + + gpuErrchk(cudaMalloc(&depth_data_GPU, num_pixels * sizeof(uint16_t))); + gpuErrchk(cudaMalloc(&vox_tsdf_GPU, num_voxels * sizeof(float))); + + gpuErrchk(cudaMalloc(&vox_limits_GPU, num_voxels * sizeof(unsigned char))); + gpuErrchk(cudaMalloc(&width_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&height_GPU, sizeof(int))); + gpuErrchk(cudaMalloc(&vol_number_GPU, sizeof(int))); + + gpuErrchk(cudaMemcpy(boundaries_GPU, boundaries, 6 * sizeof(float), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(vox_grid_GPU, vox_grid, num_voxels * sizeof(unsigned char), cudaMemcpyHostToDevice)); + + gpuErrchk(cudaMemcpy(depth_data_GPU, depth_data, num_pixels * sizeof(uint16_t), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(width_GPU, &width, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(height_GPU, &height, sizeof(int), cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(vol_number_GPU, &vol_number, sizeof(int), cudaMemcpyHostToDevice)); + + gpuErrchk(cudaMemset(vox_limits_GPU, 0, num_voxels * sizeof(unsigned char))); + gpuErrchk(cudaMemset(vox_tsdf_GPU, 0, num_voxels * sizeof(float))); + + + + end_timer(t1, "Prepare duration"); + + t1 = start_timer(); + int NUM_BLOCKS = int((num_voxels + size_t(NUM_THREADS) - 1) / NUM_THREADS); + + SquaredDistanceTransform_stanford << <NUM_BLOCKS, NUM_THREADS >> > (depth_data_GPU, vox_grid_GPU, vox_tsdf_GPU, vox_limits_GPU, + width_GPU, height_GPU, + boundaries_GPU, vol_number_GPU, parameters_GPU); + + gpuErrchk(cudaPeekAtLastError()); + gpuErrchk(cudaDeviceSynchronize()); + + + end_timer(t1, "SquaredDistanceTransform duration"); + + cudaMemcpy(vox_tsdf, vox_tsdf_GPU, num_voxels * sizeof(float), cudaMemcpyDeviceToHost); + cudaMemcpy(vox_limits, vox_limits_GPU, num_voxels * sizeof(unsigned char), cudaMemcpyDeviceToHost); + + cudaFree(boundaries_GPU); + cudaFree(vox_grid_GPU); + cudaFree(depth_data_GPU); + cudaFree(vox_tsdf_GPU); + cudaFree(vox_limits_GPU); + cudaFree(width_GPU); + cudaFree(height_GPU); + cudaFree(vol_number_GPU); + + end_timer(t1, "cleanup duration"); + + FlipTSDF_CPP(vox_tsdf); + + +} +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +extern "C" { + void get_point_cloud(float baseline, + unsigned char* depth_data, + float* point_cloud, + int width, + int height + ) { + get_point_cloud_CPP(baseline, + depth_data, + point_cloud, + width, + height + ); + } + void get_point_cloud_stanford(uint16_t* depth_data, + float* point_cloud, + int width, + int height) { + get_point_cloud_stanford_CPP(depth_data, + point_cloud, + width, + height); + } + + + void get_voxels( + /// //////////////////////////////////////////////////////////////////////////////// + unsigned char* depth_data, + /// //////////////////////////////////////////////////////////////////////////////// + float* point_cloud, + int width, int height, + float* boundaries, + int vol_number, + unsigned char* vox_grid, + + /// //////////////////////////////////////////////////////////////////////////////// + float* depth_mapping_3d + /// //////////////////////////////////////////////////////////////////////////////// + ) { + get_voxels_CPP( + /// //////////////////////////////////////////////////////////////////////////////// + depth_data, + /// //////////////////////////////////////////////////////////////////////////////// + point_cloud, + width, height, + boundaries, + vol_number, + vox_grid, + /// //////////////////////////////////////////////////////////////////////////////// + depth_mapping_3d + /// //////////////////////////////////////////////////////////////////////////////// + ); + } + + void get_gt(float* point_cloud, + int point_cloud_size, + float* boundaries, + unsigned char* gt_grid) { + get_gt_CPP(point_cloud, + point_cloud_size, + boundaries, + gt_grid); + } + + void FTSDFDepth(unsigned char* depth_data, + unsigned char* vox_grid, + float* vox_tsdf, + unsigned char* vox_limits, + float baseline, + int width, + int height, + float* boundaries, + int vol_number) { + FTSDFDepth_CPP(depth_data, + vox_grid, + vox_tsdf, + vox_limits, + baseline, + width, + height, + boundaries, + vol_number); + } + + void FTSDFDepth_stanford(uint16_t* depth_data, + unsigned char* vox_grid, + float* vox_tsdf, + unsigned char* vox_limits, + int width, + int height, + float* boundaries, + int vol_number) { + FTSDFDepth_stanford_CPP(depth_data, + vox_grid, + vox_tsdf, + vox_limits, + width, + height, + boundaries, + vol_number); + } + void downsample_grid(unsigned char* vox_grid, + unsigned char* vox_grid_down) { + downsample_grid_CPP(vox_grid, + vox_grid_down); + } + void downsample_limits(unsigned char* vox_grid, + unsigned char* vox_grid_down) { + downsample_limits_CPP(vox_grid, + vox_grid_down); + } + void setup(int device, int num_threads, + float v_unit, float v_margin, + float f, float sensor_w, float sensor_h, + int vox_size_x, int vox_size_y, int vox_size_z, + int debug_flag, + /////////////////////////////////////////////////////// + float cam_height, + float cam_back + ) { + setup_CPP(device, num_threads, + v_unit, v_margin, + f, sensor_w, sensor_h, + vox_size_x, vox_size_y, vox_size_z, + debug_flag, + /////////////////////////////////////////////////////// + cam_height, + cam_back); + } + + + void finish() { + clear_parameters_GPU(); + } +} \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/src/lib_mdbnet360.so b/Mona-SSC/Mona-SSC/MDBNet360_GDP/src/lib_mdbnet360.so new file mode 100644 index 0000000000000000000000000000000000000000..5f2a9e6d14b8fff5cb6707900dbe98949179eb52 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/src/lib_mdbnet360.so differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/post_process.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/post_process.py new file mode 100644 index 0000000000000000000000000000000000000000..644ba4188159dc820aac35a162031fb66549c65e --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/post_process.py @@ -0,0 +1,366 @@ +# Based on: https://gitlab.com/UnBVision/edgenet360/-/blob/master/lib_edgenet360/post_process.py?ref_type=heads + +import numpy as np + + +def voxel_filter(vox_orig): + + sx, sy, sz = vox_orig.shape + + min_supp=2 + filter3d = np.zeros((5, 5, 5), dtype=np.uint8) + + filter3d[0:5,2,2] = 1 + filter3d[2,2,0:5] = 1 + filter3d[2,0:5,2] = 1 + filter3d[2, 2, 2] = 0 + + vox=np.zeros((sx+4, sy+4, sz+4),dtype=np.uint8) + vox[2:-2,2:-2,2:-2] = vox_orig.copy() + + filtered = vox_orig.copy() + + for x in range(sx): + print("%d%%" % (100 * x/sx), end="\r") + for y in range(sy): + for z in range(sz): + _x, _y, _z = x+2, y+2, z+2 + cl = vox[_x, _y, _z] + + if cl==0: + continue + + sub_vol = vox[_x-2:_x+3,_y-2:_y+3,_z-2:_z+3].copy() + sub_vol[sub_vol!=cl] = 0 + sub_vol[sub_vol==cl] = 1 + + filtered[x,y,z] = vox[_x,_y,_z] * np.clip(np.sum(sub_vol * filter3d)- min_supp -1, 0, 1) + return filtered + + +def remove_internal_voxels(vox_orig): + + sx, sy, sz = vox_orig.shape + + vox=np.ones((sx+2, sy+2, sz+2),dtype=np.uint8) + vox[1:-1,1:-1,1:-1] = np.array(vox_orig>0, dtype=np.uint8) + + filtered = vox_orig.copy() + + for x in range(sx): + print("%d%%" % (100 * x/sx), end="\r") + for y in range(sy): + for z in range(sz): + _x, _y, _z = x+1, y+1, z+1 + cl = vox[_x, _y, _z] + + if cl==0: + continue + + qtty = np.sum(vox[_x-1:_x+2,_y-1:_y+2,_z-1:_z+2].copy()) + + if qtty==27: + filtered[x,y,z] = 0 + else: + filtered[x,y,z] = vox_orig[x,y,z] + return filtered + +def remove_internal_voxels_v2(vox_orig, camx, camy, camz, v_unit): + + v_unit = v_unit * 4 + + sx, sy, sz = vox_orig.shape + x, y, z = int(sx/2), int(camy//v_unit), int(sz/2) + + instances = np.zeros(vox_orig.shape, dtype=int) + + void = 2**30 -1 + + instances [x, y, z] = void + vox_orig[x, y, z] = 0 + + instance_count = 1 + + for x in range(sx): + print("finding void space %d%%"% (100 * x/sx), end="\r" ) + for y in range(sy): + for z in range(sz): + cl = vox_orig[x, y, z] + if cl>0: + continue + x_start, x_end = max(0,x-1), min(sx,x+2) + y_start, y_end = max(0,y-1), min(sy,y+2) + z_start, z_end = max(0,z-1), min(sz,z+2) + + sub_vox = vox_orig[x_start:x_end, y_start:y_end, z_start:z_end] + sub_ins = instances[x_start:x_end, y_start:y_end, z_start:z_end] + + inst = np.unique(sub_ins[sub_vox==cl] ) + + if len(inst) == 0 or max(inst)==0: + instance_count += 1 + sub_ins[sub_vox==cl]=instance_count + else: + current_instance = max(inst) + sub_ins[sub_vox==cl] = current_instance + for inst_merge in inst: + if inst_merge==0: + continue + instances[instances==inst_merge] = current_instance + + print(" ", end="\r") + + for x in range(sx): + print("%d%%"% (100 * x/sx), end="\r") + for y in range(sy): + for z in range(sz): + cl = vox_orig[x, y, z] + if cl==0 or cl==255: + continue + xi, xf = max(0,x-1), min(sx,x+2) + yi, yf = max(0,y-1), min(sy,y+2) + zi, zf = max(0,z-1), min(sz,z+2) + sub_ins = instances[xi:xf,yi:yf,zi:zf].copy() + qtty = np.sum(np.array(sub_ins==void,dtype=np.uint8)) + + if qtty == 0: + vox_orig[x, y, z] = 0 + + instances[instances!=void]=0 + instances[instances==void]=1 + + return vox_orig, np.array(instances,dtype=np.uint8) + + + +def instance_remover(vox_orig, min_size=15): + + sx, sy, sz = vox_orig.shape + + instances = np.zeros(vox_orig.shape, dtype=int) + + instance_count = 0 + + for x in range(sx): + print("%d%%"% (100 * x/sx), end="\r" ) + for y in range(sy): + for z in range(sz): + cl = vox_orig[x, y, z] + if cl==0: + continue + x_start, x_end = max(0,x-1), min(sx,x+2) + y_start, y_end = max(0,y-1), min(sy,y+2) + z_start, z_end = max(0,z-1), min(sz,z+2) + + sub_vox = vox_orig[x_start:x_end, y_start:y_end, z_start:z_end] + sub_ins = instances[x_start:x_end, y_start:y_end, z_start:z_end] + + inst = np.unique(sub_ins[sub_vox==cl] ) + + if len(inst) == 0 or max(inst)==0: + instance_count += 1 + sub_ins[sub_vox==cl]=instance_count + else: + current_instance = max(inst) + sub_ins[sub_vox==cl] = current_instance + for inst_merge in range(len(inst)-1): + if inst_merge==0: + continue + instances[instances==inst_merge] = current_instance + + for i in range(instance_count+1): + if i == 0: + continue + members = len(instances[instances==i]) + + if members<min_size: + vox_orig[instances==i] = 0 + + return vox_orig + + + +def voxel_fill(vox_orig): + from scipy import stats + + sx, sy, sz = vox_orig.shape + + vox=np.zeros((sx+2, sy+2, sz+2),dtype=np.uint8) + vox[1:-1,1:-1,1:-1] = vox_orig.copy() + + filtered = vox_orig.copy() + + filter2d = np.zeros((3, 3, 3, 3), dtype=np.uint8) + + filter2d[0,1,:,:] = 1 + filter2d[1,:,1,:] = 1 + filter2d[2,:,:,1] = 1 + filter2d[:,1, 1, 1] = 0 + + for x in range(sx): + print("%d%%"% (100 * x/sx), end="\r" ) + + for y in range(sy): + for z in range(sz): + _x, _y, _z = x+1, y+1, z+1 + + class_v = np.zeros((3,),dtype=np.uint8) + sup_v = np.zeros((3,),dtype=np.uint8) + for filter_idx in range(3): + sub_vol = vox[_x - 1:_x + 2, _y - 1:_y + 2, _z - 1:_z + 2].copy() * filter2d[filter_idx] + sub_vol_flat = sub_vol[sub_vol != 0] + if len(sub_vol_flat) == 0: + continue + cl = stats.mode(sub_vol_flat)[0][0] + sub_vol[sub_vol != cl] = 0 + sub_vol[sub_vol == cl] = 1 + support = np.sum(sub_vol) + if support > 4: + class_v[filter_idx] = cl + sup_v[filter_idx] = support + cl = class_v[np.argmax(sup_v, axis=-1)] + if cl > 0: + filtered[x, y, z] = cl + + return filtered + + +def fill_limits_vox(vox, max_x,min_x, max_z,min_z): + + xs, ys, zs = 0, 0, 0 + xe, ye, ze = np.array(vox.shape) - 1 + + for x in range(vox.shape[0]): + if np.sum(vox[x,:,:])>0: + xs=x + break + for x in range(vox.shape[0]): + if np.sum(vox[vox.shape[0]-x-1,:,:])>0: + xe=vox.shape[0]-x-1 + break + for z in range(vox.shape[2]): + if np.sum(vox[:,:,z])>0: + zs=z + break + for z in range(vox.shape[2]): + if np.sum(vox[:,:,vox.shape[2]-z-1])>0: + ze=vox.shape[2]-z-1 + break + for y in range(vox.shape[1]): + if np.sum(vox[:,vox.shape[1]-y-1,:])>0: + ye=vox.shape[1]-y-1 + break + + + #################################################################################################### + # check the scene coverage space + if not ((max_x + min_x)> 60 or (max_z + min_z)>60): + + #clear the voxels outside the specified X boundaries + vox[:min_x, :, :] = 255 + vox[max_x+1:, :, :] = 255 + # clear the voxels outside the specified Z boundaries + vox[:, :, :min_z] = 255 + vox[:, :, max_z+1:] = 255 + + + # Set the walls before the boundaries directly + vox[max(xs-1, 0), 1:ye + 1, zs:ze + 1] = 3 + vox[min(xe, vox.shape[0]-1), 1:ye + 1, zs:ze + 1] = 3 + vox[xs:xe + 1, 1:ye, max(zs-1, 0)] = 3 + vox[xs:xe + 1, 1:ye, min(ze, vox.shape[2]-1)] = 3 + vox[xs, 1:ye+1, zs:ze+1][vox[xs, 1:ye+1, zs:ze+1] == 0] = 3 + vox[xe, 1:ye+1, zs:ze+1][vox[xe, 1:ye+1, zs:ze+1] == 0] = 3 + vox[xs:xe+1, 1:ye, zs][vox[xs:xe+1, 1:ye, zs] == 0] = 3 + vox[xs:xe+1, 1:ye, ze][vox[xs:xe+1, 1:ye, ze] == 0] = 3 + + # Set the floor + vox[min_x:max_x + 1, 0, min_z:max_z + 1] = 2 + + # Set the ceiling + vox[min_x:max_x + 1, ye-7, min_z:max_z + 1] = 1 + + + else: + # Set the walls on the boundaries + vox[max(xs-1, 0), 1:ye + 1, zs:ze + 1] = 3 + vox[min(xe, vox.shape[0]-1), 1:ye + 1, zs:ze + 1] = 3 + vox[xs:xe + 1, 1:ye, max(zs-1, 0)] = 3 + vox[xs:xe + 1, 1:ye, min(ze, vox.shape[2]-1)] = 3 + vox[xs, 1:ye+1, zs:ze+1][vox[xs, 1:ye+1, zs:ze+1] == 0] = 3 + vox[xe, 1:ye+1, zs:ze+1][vox[xe, 1:ye+1, zs:ze+1] == 0] = 3 + vox[xs:xe+1, 1:ye, zs][vox[xs:xe+1, 1:ye, zs] == 0] = 3 + vox[xs:xe+1, 1:ye, ze][vox[xs:xe+1, 1:ye, ze] == 0] = 3 + + # Set the floor + vox[xs:xe + 1, 0, zs:ze + 1] = 2 + + # Set the ceiling + vox[xs:xe + 1, ye-7, zs:ze + 1] = 1 + + + ############################################################################################################# + vox[:xs, :, :] = 255 + vox[xe+1:, :, :] = 255 + vox[:, :ys, :] = 255 + vox[:, ye-6:, :] = 255 + vox[:, :, :zs] = 255 + vox[:, :, ze+1:] = 255 + + return vox + +def fill_limits_vox_stanford(vox): + xs, ys, zs = 0, 0, 0 + xe, ye, ze = np.array(vox.shape) - 1 + + for x in range(vox.shape[0]): + if np.sum(vox[x,:,:])>0: + xs=x + break + for x in range(vox.shape[0]): + if np.sum(vox[vox.shape[0]-x-1,:,:])>0: + xe=vox.shape[0]-x-1 + break + for z in range(vox.shape[2]): + if np.sum(vox[:,:,z])>0: + zs=z + break + for z in range(vox.shape[2]): + if np.sum(vox[:,:,vox.shape[2]-z-1])>0: + ze=vox.shape[2]-z-1 + break + for y in range(vox.shape[1]): + if np.sum(vox[:,vox.shape[1]-y-1,:])>0: + ye=vox.shape[1]-y-1 + break + + vox[xs, 1:ye+1, zs:ze+1][vox[xs, 1:ye+1, zs:ze+1] == 0] = 3 + vox[xe, 1:ye+1, zs:ze+1][vox[xe, 1:ye+1, zs:ze+1] == 0] = 3 + vox[xs:xe+1, 1:ye, zs][vox[xs:xe+1, 1:ye, zs] == 0] = 3 + vox[xs:xe+1, 1:ye, ze][vox[xs:xe+1, 1:ye, ze] == 0] = 3 + vox[xs:xe+1, 0, zs:ze+1][vox[xs:xe+1, 0, zs:ze+1] == 0] = 2 + vox[xs:xe+1, ye, zs:ze+1][vox[xs:xe+1, ye, zs:ze+1] == 0] = 1 + + vox[:xs, :, :] = 255 + vox[xe+1:, :, :] = 255 + vox[:, :ys, :] = 255 + vox[:, ye+1:, :] = 255 + vox[:, :, :zs] = 255 + vox[:, :, ze+1:] = 255 + + + return vox + +def clear_out_of_boundaries(vox, max_x,min_x, max_z,min_z): + + # clear the voxels outside the specified X boundaries + vox[:min_x, :, :] = 255 + vox[max_x+1:, :, :] = 255 + + + # clear the voxels outside the specified Z boundaries + vox[:, :, :min_z] = 255 + vox[:, :, max_z+1:] = 255 + + + return vox diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/preproc.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/preproc.py new file mode 100644 index 0000000000000000000000000000000000000000..9c8ba032677518b4e7f06750f7232092ce6a9530 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/preproc.py @@ -0,0 +1,619 @@ +# By: https://gitlab.com/UnBVision/edgenet360/-/blob/master/lib_edgenet360/preproc.py?ref_type=heads + +import numpy as np +from sklearn import linear_model +import cv2 +import pandas as pd + + +PI = 3.14159265 +DISP_SCALE = 2.0 +DISP_OFFSET = -120.0 + + +def plane_estimate(fpc, a, b, c): + + X = np.ones((fpc.shape[0], 2)) + X[:,0] = fpc[:,a] + X[:,1] = fpc[:,b] + + y = fpc[:,c] + + ransac = linear_model.RANSACRegressor() + try: + ransac.fit(X, y) + return [ransac.estimator_.coef_[0], ransac.estimator_.coef_[1], ransac.estimator_.intercept_] + except: + return [1,1,1] + + + +def adjust_ceil(point_cloud, candidate, margin): + wx, wy, wz, lat, long, rd = tuple(range(6)) + + points = ((point_cloud[:, :, wy] < (candidate + margin)) & (point_cloud[:, :, wy] > (candidate - margin))) + + fpc = point_cloud[points] + + fit = plane_estimate(fpc, wx, wz, wy) + + if (abs(fit[0])<0.05) and (abs(fit[1])<0.05): + return fit[2] + else: + return candidate + + + +def get_limits(values, perc=.9, lperc=.9999): + min = np.percentile(values, lperc) + max = -np.percentile(-values, lperc) + #print(min,max) + values = values[(values >= min) & (values <= max)] + return np.percentile(values, perc), -np.percentile(-values, perc) + + +def find_limits_v2(point_cloud, perc=.9, lperc=.9999): + wx, wy, wz = tuple(range(3)) + print("l-r") + left, right = get_limits(point_cloud[:, :, wx].flatten(), perc=perc, lperc=lperc) + print(left,right) + print("b-f") + back, front = get_limits(point_cloud[:, :, wz].flatten(), perc=perc, lperc=lperc) + print(back,front) + + print("f-c") + floor, ceil = get_limits(point_cloud[:, :, wy].flatten(), perc=perc, lperc=lperc) + print(floor,ceil) + return ceil, floor, front, back, right, left + + + +def find_region(startx, starty, rgb_image, step, thin_mask): + + imff = rgb_image.copy() + h, w = imff.shape[:2] + + paint_x_start = max(0, startx - step // 2) + paint_y_start = max(0, starty - step // 2) + + paint_x_end = min(startx + step // 2, w) + paint_y_end = min(starty + step // 2, h) + + #imff = cv2.cvtColor(imff,cv2.COLOR_BGR2HSV) + + threshold = (2, 2, 2) + mask = np.zeros((h + 2, w + 2), np.uint8) + mask[1:-1,1:-1] = thin_mask + cv2.floodFill(imff, mask, (startx, starty), newVal=(255, 0, 0), loDiff=threshold, upDiff=threshold, + flags=4 | (255 << 8) | cv2.FLOODFILL_MASK_ONLY)#|cv2.FLOODFILL_FIXED_RANGE) + mask[1:-1, 1:-1] = mask[1:-1, 1:-1] & ~thin_mask + + return mask[1:-1,1:-1] + + +def radius_eq_y(a, b, c, lat, long): + return c / (np.cos(lat) - a*np.sin(lat)*np.sin(PI-long) - b*np.sin(lat)*np.cos(PI-long)) + + +def radius_eq_x(a, b, c, lat, long): + return c / (np.sin(lat)*np.cos(PI-long) - a*np.cos(lat) - b*np.sin(lat)*np.sin(PI-long)) + + +def radius_eq_z(a, b, c, lat, long): + return c / (np.sin(lat)*np.sin(PI-long) - a*np.sin(lat)*np.cos(PI-long) - b*np.cos(lat)) + + +def ang_disparity(baseline, radius, lat): + ad = np.arctan(np.sin(lat)/(baseline/radius + np.cos(lat))) - lat + ad_PI = ad+PI + c = np.stack([ad,ad_PI],axis=-1) + choice=np.argmin(abs(c), axis=-1) + return np.choose(choice, [ad,ad_PI]) + + +def pt_disparity(ang_disparity, unit_h): + return (((ang_disparity/(unit_h*PI)) - DISP_OFFSET ) * DISP_SCALE).astype(np.uint8) + + +def find_planes(pc, rgb_image, edges_image, depth_image, thin_edges, baseline): + + import matplotlib.pyplot as plt + + wx, wy, wz, lat, long, wrd = tuple(range(6)) + h,w = edges_image.shape + complete_region_mask = np.zeros((h, w), np.uint8) + inf_region_mask = np.zeros((h, w), np.uint8) + close_region_mask = np.zeros((h, w), np.uint8) + new_depth_image = depth_image.copy() + + step=75 + + combined = rgb_image.copy() + + for startx in np.arange(0,w, step): + for starty in np.arange(250, h-250, step): + + if (inf_region_mask[starty,startx] > 0) or \ + (close_region_mask[starty,startx] > 0) or \ + (complete_region_mask[starty,startx] > 0): + continue + + + paint_x_start = max(0, startx - step // 2) + paint_y_start = max(0, starty - step // 2) + + paint_x_end = min(startx + step // 2, w) + paint_y_end = min(starty + step // 2, h) + + region_mask = find_region(startx, starty, rgb_image, step, thin_edges) + edges_mask = region_mask & edges_image + + + + + + fpc1 = pc[(edges_mask>0) & ((pc[:,:,wx]!=0)|(pc[:,:,wy]!=0)|(pc[:,:,wz]!=0))] + + planes=[] + planes.append(plane_estimate(fpc1, wz, wx, wy)) # y = az + bx + c (0) + planes.append(plane_estimate(fpc1, wx, wy, wz)) # z = ax + by + c (1) + planes.append(plane_estimate(fpc1, wy, wz, wx)) # x = ay + bz + c (2) + planes=np.array(planes) + eq = np.argmin(abs(planes[:,0]) + abs(planes[:,1])) + a, b, c = planes[eq] + + height, width, __ = rgb_image.shape + unit_h = 1.0 / height + unit_w = 2.0 / width + + fpc2 = pc[region_mask>0] + #fpc = pc[paint_y_start:paint_y_end,paint_x_start:paint_x_end][region_mask[paint_y_start:paint_y_end,paint_x_start:paint_x_end]>0] + #[paint_y_start:paint_y_end,paint_x_start:paint_x_end] + + + + #print(eq, a,b,c) + if (abs(a)< 0.3 and abs(b)<0.3): + + combined[:, :, 0] = rgb_image[:, :, 0] / 2 + thin_edges / 4 + region_mask / 4 + combined[:, :, 1] = rgb_image[:, :, 1] / 2 + complete_region_mask / 2 + combined[:, :, 2] = rgb_image[:, :, 2] / 2 + inf_region_mask / 2 + #cv2.imshow("Work", combined) + #cv2.waitKey(1) + + if (eq == 0): + if (abs(a)< 0.1 and abs(b)<0.1): + a, b, c = 0., 0., np.nanmedian(fpc1[:, wy]) + rd = radius_eq_y(a, b, c, fpc2[:, lat], fpc2[:, long]) + + elif (eq == 1): + if (abs(a)< 0.1 and abs(b)<0.1): + a, b, c = 0., 0., np.nanmedian(fpc1[:, wz]) + rd = radius_eq_z(a, b, c, fpc2[:, lat], fpc2[:, long]) + + elif (eq == 2): + if (abs(a)< 0.1 and abs(b)<0.1): + a, b, c = 0., 0., np.nanmedian(fpc1[:, wx]) + rd = radius_eq_x(a, b, c, fpc2[:, lat], fpc2[:, long]) + + ad = ang_disparity(baseline, rd, fpc2[:,lat]) + + new_disparity = pt_disparity(ad, unit_h) + + if np.max(new_disparity) > 235: + #print("x:%4d y:%4d eq:%d GOOD Plane - a:%4.2f b:%4.2f c:%4.2f infinity back projection %d" + # %(startx,starty, eq, a, b, c, np.max(new_disparity))) + inf_region_mask = inf_region_mask | region_mask + elif np.min(new_disparity) < 20: + #print("x:%4d y:%4d eq:%d GOOD Plane - a:%4.2f b:%4.2f c:%4.2f too close back projection %d" + # %(startx,starty, eq, a, b, c, np.min(new_disparity))) + close_region_mask = close_region_mask | region_mask + else: + new_depth_image[region_mask>0] = new_disparity + complete_region_mask = complete_region_mask | region_mask + #print("x:%4d y:%4d eq:%d GOOD Plane - a:%4.2f b:%4.2f c:%4.2f good back projection %d-%d" + # %(startx,starty, eq, a, b, c, np.min(new_disparity), np.max(new_disparity))) + #cv2.imshow("Output", new_depth_image) + combined[:, :, 0] = rgb_image[:, :, 0] / 2 + thin_edges / 4 + combined[:, :, 1] = rgb_image[:, :, 1] / 2 + complete_region_mask / 2 + combined[:, :, 2] = rgb_image[:, :, 2] / 2 + inf_region_mask / 2 + plt.imshow(combined) + plt.draw() + plt.pause(0.0001) + #cv2.imshow("Work", combined) + #cv2.waitKey(1) + + combined[:, :, 0] = rgb_image[:, :, 0] / 2 + thin_edges / 4 + combined[:, :, 1] = rgb_image[:, :, 1] / 2 + complete_region_mask / 2 + combined[:, :, 2] = rgb_image[:, :, 2] / 2 + inf_region_mask / 2 + #cv2.imshow("Work", combined) + new_depth_image[:250] = 0 + new_depth_image[-250:] = 0 + #cv2.imshow("Output", new_depth_image) + #cv2.waitKey(1) + + return new_depth_image, complete_region_mask, edges_mask, inf_region_mask, close_region_mask + + +def get_x(radius, latitude, longitude): + return radius*np.sin(latitude)*np.cos(PI - longitude) + +def get_z(radius, latitude, longitude): + return radius*np.sin(latitude)*np.sin(PI - longitude) + +def get_y(radius, latitude, longitude): + return radius*np.cos(latitude) + + +def fix_limits(pc, depth_image, ceil_height, floor_height, front_dist, back_dist, right_dist, left_dist, baseline): + + + wx, wy, wz, lat, long, wrd = tuple(range(6)) + + fpc1 = pc[250:253,:][pc[250:253, :, wy] <1000] + __, __, ceil_height = plane_estimate(fpc1, wz, wx, wy) # y = az + bx + c (0) + + fpc1 = pc[-253:-250,:][pc[-253:-250, :, wy] <1000] + __, __, floor_height = plane_estimate(fpc1, wz, wx, wy) # y = az + bx + c (0) + + + #ceil_height = np.median(pc[248:250,:,wy]) + print("Adjusted ceil_height",ceil_height) + ##floor_height = np.median(pc[-252:-250,:,wy]) + print("Adjusted floor_height",floor_height) + new_depth_image = depth_image.copy() + h,w = depth_image.shape + unit_h = 1.0 / h + ##top + fpc = pc[:250,:][pc[:250, :, wy] == 0] + rd = radius_eq_y(0, 0, ceil_height, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[:250,:] = pt_disparity(ad, unit_h).reshape(new_depth_image[:250,:].shape) + + fpc = pc[pc[:, :, wy] > ceil_height] + rd = radius_eq_y(0, 0, ceil_height, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[pc[:, :, wy] > ceil_height] = pt_disparity(ad, unit_h) + #new_depth_image[pc[:, :, wy] > ceil_height] = 0 + pc[pc[:, :, wy] > ceil_height, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] > ceil_height, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] > ceil_height, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + + ##floor + fpc = pc[-250:,:][pc[-250:, :, wy] == 0] + rd = radius_eq_y(0, 0, floor_height, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[-250:,:] = pt_disparity(ad, unit_h).reshape(new_depth_image[-250:,:].shape) + + fpc = pc[pc[:, :, wy] < floor_height] + rd = radius_eq_y(0, 0, floor_height, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[pc[:, :, wy] < floor_height] = pt_disparity(ad, unit_h) + #new_depth_image[pc[:, :, wy] < floor_height] = 0 + pc[pc[:, :, wy] < floor_height, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] < floor_height, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] < floor_height, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + + ##left + fpc = pc[pc[:, :, wx] < left_dist] + rd = radius_eq_x(0, 0, left_dist, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[pc[:, :, wx] < left_dist] = pt_disparity(ad, unit_h) + #new_depth_image[pc[:, :, wx] < left_dist] = 0 + pc[pc[:, :, wx] < left_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] < left_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] < left_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + + ##right + fpc = pc[pc[:, :, wx] > right_dist] + rd = radius_eq_x(0, 0, right_dist, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[pc[:, :, wx] > right_dist] = pt_disparity(ad, unit_h) + #new_depth_image[pc[:, :, wx] > right_dist] = 0 + pc[pc[:, :, wx] > right_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] > right_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] > right_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + + ##back + fpc = pc[pc[:, :, wz] < back_dist] + rd = radius_eq_z(0, 0, back_dist, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[pc[:, :, wz] < back_dist] = pt_disparity(ad, unit_h) + #new_depth_image[pc[:, :, wz] < back_dist] = 0 + pc[pc[:, :, wz] < back_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] < back_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] < back_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + + + ##front + fpc = pc[pc[:, :, wz] > front_dist] + rd = radius_eq_z(0, 0, front_dist, fpc[:, lat], fpc[:, long]) + ad = ang_disparity(baseline, rd, fpc[:, lat]) + new_depth_image[pc[:, :, wz] > front_dist] = pt_disparity(ad, unit_h) + #new_depth_image[pc[:, :, wz] > front_dist] = 0 + pc[pc[:, :, wz] > front_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] > front_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] > front_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + + return new_depth_image + +### check ################################################################################################################## +def find_planes_stanford(pc, rgb_image, edges_image, depth_image, thin_edges): + + wx, wy, wz, lat, long, wrd = tuple(range(6)) + h,w = edges_image.shape + complete_region_mask = np.zeros((h, w), np.uint8) + inf_region_mask = np.zeros((h, w), np.uint8) + close_region_mask = np.zeros((h, w), np.uint8) + new_depth_image = depth_image.copy() + + zero_edges = depth_image.copy() * 0 + + depth_show = ((np.clip(new_depth_image,0,5120).astype(np.float)/5120)*255).astype(np.uint8) + cv2.imshow("Output", depth_show) + + step=35 + + combined = rgb_image.copy() + + for startx in np.arange(0,w, step): + for starty in np.arange(250, h-250, step): + + if (inf_region_mask[starty,startx] > 0) or \ + (close_region_mask[starty,startx] > 0) or \ + (complete_region_mask[starty,startx] > 0): + continue + + paint_x_start = max(0, startx - step // 2) + paint_y_start = max(0, starty - step // 2) + + paint_x_end = min(startx + step // 2, w) + paint_y_end = min(starty + step // 2, h) + + region_mask = find_region(startx, starty, rgb_image, step, zero_edges) + edges_mask = region_mask & edges_image + + + + + + fpc1 = pc[(edges_mask>0) & ((pc[:,:,wx]!=0)|(pc[:,:,wy]!=0)|(pc[:,:,wz]!=0))] + + planes=[] + planes.append(plane_estimate(fpc1, wz, wx, wy)) # y = az + bx + c (0) + planes.append(plane_estimate(fpc1, wx, wy, wz)) # z = ax + by + c (1) + planes.append(plane_estimate(fpc1, wy, wz, wx)) # x = ay + bz + c (2) + planes=np.array(planes) + eq = np.argmin(abs(planes[:,0]) + abs(planes[:,1])) + a, b, c = planes[eq] + + height, width, __ = rgb_image.shape + unit_h = 1.0 / height + unit_w = 2.0 / width + + fpc2 = pc[region_mask>0] + #fpc = pc[paint_y_start:paint_y_end,paint_x_start:paint_x_end][region_mask[paint_y_start:paint_y_end,paint_x_start:paint_x_end]>0] + #[paint_y_start:paint_y_end,paint_x_start:paint_x_end] + + + + #print(eq, a,b,c) + if (abs(a)< 0.3 and abs(b)<0.3): + + combined[:, :, 0] = np.clip(rgb_image[:, :, 0] / 2 + thin_edges / 4 + region_mask / 2,0,255) + combined[:, :, 1] = np.clip(rgb_image[:, :, 1] / 2 + thin_edges / 4 + complete_region_mask / 2,0,255) + combined[:, :, 2] = np.clip(rgb_image[:, :, 2] / 2 + thin_edges / 4 + inf_region_mask / 2,0,255) + cv2.imshow("Work", combined) + cv2.waitKey(1) + + if (eq == 0): + if (abs(a)< 0.1 and abs(b)<0.1): + a, b, c = 0., 0., np.nanmedian(fpc1[:, wy]) + rd = radius_eq_y(a, b, c, fpc2[:, lat], fpc2[:, long]) + + elif (eq == 1): + if (abs(a)< 0.1 and abs(b)<0.1): + a, b, c = 0., 0., np.nanmedian(fpc1[:, wz]) + rd = radius_eq_z(a, b, c, fpc2[:, lat], fpc2[:, long]) + + elif (eq == 2): + if (abs(a)< 0.1 and abs(b)<0.1): + a, b, c = 0., 0., np.nanmedian(fpc1[:, wx]) + rd = radius_eq_x(a, b, c, fpc2[:, lat], fpc2[:, long]) + + point_depth = (rd * 512).astype(np.uint16) + + if np.max(point_depth)/512. > 10.: + #print("x:%4d y:%4d eq:%d GOOD Plane - a:%4.2f b:%4.2f c:%4.2f infinity back projection %d" + # %(startx,starty, eq, a, b, c, np.max(new_disparity))) + inf_region_mask = inf_region_mask | region_mask + elif np.min(point_depth)/512. < .3: + #print("x:%4d y:%4d eq:%d GOOD Plane - a:%4.2f b:%4.2f c:%4.2f too close back projection %d" + # %(startx,starty, eq, a, b, c, np.min(new_disparity))) + close_region_mask = close_region_mask | region_mask + else: + new_depth_image[region_mask>0] = point_depth + complete_region_mask = complete_region_mask | region_mask + #print("x:%4d y:%4d eq:%d GOOD Plane - a:%4.2f b:%4.2f c:%4.2f good back projection %d-%d" + # %(startx,starty, eq, a, b, c, np.min(new_disparity), np.max(new_disparity))) + depth_show = ((np.clip(new_depth_image, 0, 5120).astype(np.float) / 5120) * 255).astype(np.uint8) + cv2.imshow("Output", depth_show) + combined[:, :, 0] = np.clip(rgb_image[:, :, 0] / 2 + thin_edges / 4 + region_mask / 2,0,255) + combined[:, :, 1] = np.clip(rgb_image[:, :, 1] / 2 + thin_edges / 4 + complete_region_mask / 2,0,255) + combined[:, :, 2] = np.clip(rgb_image[:, :, 2] / 2 + thin_edges / 4 + inf_region_mask / 2,0,255) + cv2.imshow("Work", combined) + cv2.waitKey(1) + + combined[:, :, 0] = rgb_image[:, :, 0] / 2 + thin_edges / 4 + combined[:, :, 1] = rgb_image[:, :, 1] / 2 + complete_region_mask / 2 + combined[:, :, 2] = rgb_image[:, :, 2] / 2 + inf_region_mask / 2 + cv2.imshow("Work", combined) + new_depth_image[:250] = 0 + new_depth_image[-250:] = 0 + depth_show = ((np.clip(new_depth_image,0,5120).astype(np.float)/5120)*255).astype(np.uint8) + cv2.imshow("Output", depth_show) + cv2.waitKey(1) + + return new_depth_image, complete_region_mask, edges_mask, inf_region_mask, close_region_mask + +######**********************************************************************************************************####### + +def fix_limits_stanford(pc, depth_image, ceil_height, floor_height, front_dist, back_dist, right_dist, left_dist): + wx, wy, wz, lat, long, wrd = tuple(range(6)) + + w_offset = 0.08 + + front_dist, back_dist, right_dist, left_dist = front_dist+w_offset, back_dist-w_offset, right_dist+w_offset, left_dist-w_offset + + fpc1 = pc[250:253,:][pc[250:253, :, wy] <1000] + __, __, ceil_height = plane_estimate(fpc1, wz, wx, wy) # y = az + bx + c (0) + + fpc1 = pc[-253:-250,:][pc[-253:-250, :, wy] <1000] + __, __, floor_height = plane_estimate(fpc1, wz, wx, wy) # y = az + bx + c (0) + + + #ceil_height = np.median(pc[248:250,:,wy]) + print("Adjusted ceil_height",ceil_height) + ##floor_height = np.median(pc[-252:-250,:,wy]) + print("Adjusted floor_height",floor_height) + new_depth_image = depth_image.copy() + h,w = depth_image.shape + unit_h = 1.0 / h + ##top + fpc = pc[:250,:][pc[:250, :, wy] < 1000] + rd = radius_eq_y(0, 0, ceil_height, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[:250,:] = point_depth.reshape(new_depth_image[:250,:].shape) + + fpc = pc[pc[:, :, wy] > ceil_height] + rd = radius_eq_y(0, 0, ceil_height, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wy] > ceil_height] = point_depth + pc[pc[:, :, wy] > ceil_height, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] > ceil_height, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] > ceil_height, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + + ##floor + fpc = pc[-250:,:][pc[-250:, :, wy] < 1000] + rd = radius_eq_y(0, 0, floor_height, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[-250:,:] = point_depth.reshape(new_depth_image[-250:,:].shape) + + fpc = pc[pc[:, :, wy] < floor_height] + rd = radius_eq_y(0, 0, floor_height, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wy] < floor_height] = point_depth + #new_depth_image[pc[:, :, wy] < floor_height] = 0 + pc[pc[:, :, wy] < floor_height, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] < floor_height, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] < floor_height, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + + ##left + fpc = pc[pc[:, :, wx] < left_dist] + rd = radius_eq_x(0, 0, left_dist, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wx] < left_dist] = point_depth + #new_depth_image[pc[:, :, wx] < left_dist] = 0 + pc[pc[:, :, wx] < left_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] < left_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] < left_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + + ##right + fpc = pc[pc[:, :, wx] > right_dist] + rd = radius_eq_x(0, 0, right_dist, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wx] > right_dist] = point_depth + #new_depth_image[pc[:, :, wx] > right_dist] = 0 + pc[pc[:, :, wx] > right_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] > right_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wx] > right_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + + ##back + fpc = pc[pc[:, :, wz] < back_dist] + rd = radius_eq_z(0, 0, back_dist, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wz] < back_dist] = point_depth + #new_depth_image[pc[:, :, wz] < back_dist] = 0 + pc[pc[:, :, wz] < back_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] < back_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] < back_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + + + ##front + fpc = pc[pc[:, :, wz] > front_dist] + rd = radius_eq_z(0, 0, front_dist, fpc[:, lat], fpc[:, long]) + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wz] > front_dist] = point_depth + #new_depth_image[pc[:, :, wz] > front_dist] = 0 + pc[pc[:, :, wz] > front_dist, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] > front_dist, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wz] > front_dist, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + + return new_depth_image +######################################################################################################################## End check + +def fix_heigth_stanford(pc, depth_image, floor_height, ceil_height): + wx, wy, wz, lat, long, wrd = tuple(range(6)) + + new_depth_image = depth_image.copy() + h,w = depth_image.shape + unit_h = 1.0 / h + + ##ceil + fpc = pc[pc[:, :, wy] > ceil_height] + rd = radius_eq_y(0, 0, ceil_height, fpc[:, lat], fpc[:, long]) + + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wy] > ceil_height] = point_depth + pc[pc[:, :, wy] > ceil_height, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] > ceil_height, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] > ceil_height, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + + ##floor + fpc = pc[pc[:, :, wy] < floor_height] + rd = radius_eq_y(0, 0, floor_height, fpc[:, lat], fpc[:, long]) + + point_depth = (rd * 512).astype(np.uint16) + new_depth_image[pc[:, :, wy] < floor_height] = point_depth + pc[pc[:, :, wy] < floor_height, wx] = get_x(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] < floor_height, wz] = get_z(rd, fpc[:, lat], fpc[:, long]) + pc[pc[:, :, wy] < floor_height, wy] = get_y(rd, fpc[:, lat], fpc[:, long]) + + return new_depth_image + + + +import math + +# Checks if a matrix is a valid rotation matrix. +def isRotationMatrix(R) : + Rt = np.transpose(R) + shouldBeIdentity = np.dot(Rt, R) + I = np.identity(3, dtype = R.dtype) + n = np.linalg.norm(I - shouldBeIdentity) + return n < 1e-6 + + + +# Calculates rotation matrix to euler angles +# The result is the same as MATLAB except the order +# of the euler angles ( x and z are swapped ). +def rotationMatrixToEulerAngles(R): + assert (isRotationMatrix(R)) + + sy = math.sqrt(R[0, 0] * R[0, 0] + R[1, 0] * R[1, 0]) + + singular = sy < 1e-6 + + if not singular: + x = math.atan2(R[2, 1], R[2, 2]) + y = math.atan2(-R[2, 0], sy) + z = math.atan2(R[1, 0], R[0, 0]) + else: + x = math.atan2(-R[1, 2], R[1, 1]) + y = math.atan2(-R[2, 0], sy) + z = 0 + + return np.array([x, y, z]) + + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/py_cuda.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/py_cuda.py new file mode 100644 index 0000000000000000000000000000000000000000..872224a572497b71177c551bd97c72d0e1008925 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/py_cuda.py @@ -0,0 +1,295 @@ +""" +first combile lib_mdbnet360.cu: +nvcc -std=c++11 --ptxas-options=-v --compiler-options '-fPIC' -o lib_preproc.so --shared lib_mdbnet360.cu +""" + +import ctypes +import numpy as np +import cv2 +import os +import matplotlib.pyplot as plt + +SENSOR_W = 640 # perspective image dim +SENSOR_H = 480 +VOXEL_SHAPE = (240,144,240) + + +def get_segmentation_class_map(): + return np.array([0, 1, 2, 3, 4, 11, 5, 6, 7, 8, 8, 10, 10, 10, 11, 11, 9, 8, 11, 11, + 11, 11, 11, 11, 11, 11, 11, 10, 10, 11, 8, 10, 11, 9, 11, 11, 11], dtype=np.int32) +def get_class_names(): + return ["ceil.", "floor", "wall ", "wind.", "chair", "bed ", "sofa ", "table", "tvs ", "furn.", "objs."] + +_lib = ctypes.CDLL(os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))),'src/lib_mdbnet360.so')) + + +_lib.setup.argtypes = (ctypes.c_int, + ctypes.c_int, + ctypes.c_float, + ctypes.c_float, + ctypes.c_float, + ctypes.c_float, + ctypes.c_float, + ctypes.c_int, + ctypes.c_int, + ctypes.c_int, + ctypes.c_int, + ctypes.c_float, # cam hight param + ctypes.c_float, # cam go back param + ) + +def lib_mdbnet360_setup(device=0, num_threads=1024, v_unit=0.02, v_margin=0.24, + f=518.8, sensor_w=640, sensor_h=480, + vox_shape=None, + debug=0, cam_h=1.0, cam_b=1.0): + + global _lib, VOXEL_SHAPE + + if vox_shape is not None: + VOXEL_SHAPE = vox_shape + + + + _lib.setup(ctypes.c_int(device), + ctypes.c_int(num_threads), + ctypes.c_float(v_unit), + ctypes.c_float(v_margin), + ctypes.c_float(f), + ctypes.c_float(sensor_w), + ctypes.c_float(sensor_h), + ctypes.c_int(VOXEL_SHAPE[0]), + ctypes.c_int(VOXEL_SHAPE[1]), + ctypes.c_int(VOXEL_SHAPE[2]), + ctypes.c_int(debug), + ctypes.c_float(cam_h), + ctypes.c_float(cam_b) + ) + + +_lib.get_point_cloud.argtypes = (ctypes.c_float, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_int, + ctypes.c_int, + ) + +def get_point_cloud(depth_file, baseline): + global _lib + + depth_image = cv2.imread(depth_file, cv2.IMREAD_ANYDEPTH) + + height, width = depth_image.shape + + num_pixels = height * width + + point_cloud = np.zeros((height, width, 6), dtype=np.float32) + + plt.imshow(depth_image) + + _lib.get_point_cloud(ctypes.c_float(baseline), + depth_image.ctypes.data_as(ctypes.c_void_p), + point_cloud.ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(width), + ctypes.c_int(height) + ) + return point_cloud, depth_image + + +_lib.get_voxels.argtypes = (ctypes.c_void_p, # for depth image + ctypes.c_void_p, + ctypes.c_int, + ctypes.c_int, + ctypes.c_void_p, + ctypes.c_int, + ctypes.c_void_p, + ctypes.c_void_p, # for depth_mapping_3d + + ) + + +def get_voxels(depth_image,point_cloud, point_cloud_shape, min_x, max_x, min_y, max_y, min_z, max_z, vol_number=1): + global _lib, VOXEL_SHAPE + + boundaries = np.array([min_x, max_x, min_y, max_y, min_z, max_z], dtype=np.float32) + vox_grid = np.zeros(VOXEL_SHAPE,dtype=np.uint8) + ################## + # calculate the number of points in the point cloud + num_points = point_cloud_shape[0] * point_cloud_shape[1] + num_voxels = VOXEL_SHAPE[0] * VOXEL_SHAPE[1] * VOXEL_SHAPE[2] + depth_mapping = np.ones(num_voxels, dtype=np.float32) * (-1) + + ################## + _lib.get_voxels(depth_image.ctypes.data_as(ctypes.c_void_p), # added depth image + point_cloud.ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(point_cloud_shape[1]), + ctypes.c_int(point_cloud_shape[0]), + boundaries.ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(vol_number), + vox_grid.ctypes.data_as(ctypes.c_void_p), + + ################################################# + depth_mapping.ctypes.data_as(ctypes.c_void_p), + + ################################################# + ) + depth_mapping = depth_mapping.astype(np.int64) + return vox_grid, depth_mapping + + +_lib.downsample_grid.argtypes = (ctypes.c_void_p, + ctypes.c_void_p + ) + +def downsample_grid(in_vox_grid): + global _lib, VOXEL_SHAPE + + out_vox_grid = np.zeros((VOXEL_SHAPE[0]//4,VOXEL_SHAPE[1]//4,VOXEL_SHAPE[2]//4 ),dtype=np.uint8) + + _lib.downsample_grid(in_vox_grid.ctypes.data_as(ctypes.c_void_p), + out_vox_grid.ctypes.data_as(ctypes.c_void_p) + ) + return out_vox_grid + + +_lib.downsample_limits.argtypes = (ctypes.c_void_p, + ctypes.c_void_p + ) + +def downsample_limits(in_vox_grid): + global _lib, VOXEL_SHAPE + + out_vox_grid = np.zeros((VOXEL_SHAPE[0]//4,VOXEL_SHAPE[1]//4,VOXEL_SHAPE[2]//4 ),dtype=np.uint8) + + _lib.downsample_limits(in_vox_grid.ctypes.data_as(ctypes.c_void_p), + out_vox_grid.ctypes.data_as(ctypes.c_void_p) + ) + return out_vox_grid + +_lib.FTSDFDepth.argtypes = (ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_float, + ctypes.c_int, + ctypes.c_int, + ctypes.c_void_p, + ctypes.c_int + ) + +def get_ftsdf(depth_image, vox_grid, min_x, max_x, min_y, max_y, min_z, max_z, + baseline, vol_number=1): + global _lib, VOXEL_SHAPE + + boundaries = np.array([min_x, max_x, min_y, max_y, min_z, max_z], dtype=np.float32) + height, width = depth_image.shape + vox_tsdf = np.zeros(VOXEL_SHAPE,dtype=np.float32) + vox_limits = np.zeros(VOXEL_SHAPE,dtype=np.uint8) + + _lib.FTSDFDepth(depth_image.ctypes.data_as(ctypes.c_void_p), + vox_grid.ctypes.data_as(ctypes.c_void_p), + vox_tsdf.ctypes.data_as(ctypes.c_void_p), + vox_limits.ctypes.data_as(ctypes.c_void_p), + ctypes.c_float(baseline), + ctypes.c_int(width), + ctypes.c_int(height), + boundaries.ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(vol_number) + ) + return vox_tsdf, vox_limits + +""" +########################################## Stanford2D3D ################################################# +def get_point_cloud_stanford(in_depth_map, in_rgb_file=None, y_rt=None): + global _lib + + out_bgr_image=None + + PI = 3.14159265 + + in_depth_image = cv2.imread(in_depth_map, cv2.IMREAD_ANYDEPTH) + out_depth_image = in_depth_image.copy() + + + height, width = in_depth_image.shape + + if not y_rt is None: + + shift_point = int((y_rt * width) / (2*PI)) + + out_depth_image[:,-shift_point:] = in_depth_image[:,:shift_point] + out_depth_image[:,:-shift_point] = in_depth_image[:,shift_point:] + + if not in_rgb_file is None: + in_bgr_image = cv2.imread(in_rgb_file, cv2.IMREAD_COLOR) + out_bgr_image = in_bgr_image.copy() + out_bgr_image[:,-shift_point:] = in_bgr_image[:,:shift_point] + out_bgr_image[:,:-shift_point] = in_bgr_image[:,shift_point:] + + point_cloud = np.zeros((height, width, 6), dtype=np.float32) + + _lib.get_point_cloud_stanford(out_depth_image.ctypes.data_as(ctypes.c_void_p), + point_cloud.ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(width), + ctypes.c_int(height) + ) + + if not out_bgr_image is None: + return point_cloud, out_depth_image, out_bgr_image + else: + return point_cloud, out_depth_image + +################################################################################# + +_lib.get_gt.argtypes = (ctypes.c_void_p, + ctypes.c_int, + ctypes.c_void_p, + ctypes.c_void_p + ) + +def get_gt(point_cloud, min_x, max_x, min_y, max_y, min_z, max_z): + global _lib, voxel_shape + + boundaries = np.array([min_x, max_x, min_y, max_y, min_z, max_z], dtype=np.float32) + + + gt_grid = np.zeros((VOXEL_SHAPE[0]//2, VOXEL_SHAPE[1]//4, VOXEL_SHAPE[2]//2),dtype=np.uint8) + + _lib.get_gt(point_cloud.flatten().ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(point_cloud.shape[0]), + boundaries.ctypes.data_as(ctypes.c_void_p), + gt_grid.ctypes.data_as(ctypes.c_void_p) + ) + return gt_grid + +################################################################################## +_lib.FTSDFDepth_stanford.argtypes = (ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_void_p, + ctypes.c_int, + ctypes.c_int, + ctypes.c_void_p, + ctypes.c_int + ) + + +def get_ftsdf_stanford(depth_image, vox_grid, min_x, max_x, min_y, max_y, min_z, max_z, vol_number=1): + global _lib, VOXEL_SHAPE + + boundaries = np.array([min_x, max_x, min_y, max_y, min_z, max_z], dtype=np.float32) + height, width = depth_image.shape + vox_tsdf = np.zeros(VOXEL_SHAPE,dtype=np.float32) + vox_limits = np.zeros(VOXEL_SHAPE,dtype=np.uint8) + + _lib.FTSDFDepth_stanford(depth_image.ctypes.data_as(ctypes.c_void_p), + vox_grid.ctypes.data_as(ctypes.c_void_p), + vox_tsdf.ctypes.data_as(ctypes.c_void_p), + vox_limits.ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(width), + ctypes.c_int(height), + boundaries.ctypes.data_as(ctypes.c_void_p), + ctypes.c_int(vol_number) + ) + return vox_tsdf, vox_limits +""" + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/spher_cubic_proj.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/spher_cubic_proj.py new file mode 100644 index 0000000000000000000000000000000000000000..048c28d1cc0cf2d9dd450c6a3238ab298975ec29 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/spher_cubic_proj.py @@ -0,0 +1,659 @@ +import argparse +import os +import numpy as np +import cv2 +import math + +os.environ['TF_CPP_MIN_VLOG_LEVEL'] = '3' +os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' + + +CV_PI = 3.141592 +#DATA_PATH = './data' +#OUTPUT_PATH = './output' +SENSOR_W = 640 # perspective image dim +SENSOR_H = 480 + +def spher_cubic_proj(depth_file, rgb_file, out_prefix): + + spher_rgb = cv2.imread(rgb_file, cv2.IMREAD_COLOR) + spher_depth = cv2.imread(depth_file, cv2.IMREAD_ANYDEPTH) + print('spher_rgb shape', spher_rgb.shape) + print('spher_depth shape', spher_depth.shape) + height, width, channels = spher_rgb.shape + + + ########################################### Generate 4 views projection using sphere to cubic projection ############################## + rgb_views = [] + depth_views = [] + side_range = (SENSOR_W / float(SENSOR_H)) #over projection range for output width + img_out = np.zeros((SENSOR_H,SENSOR_W,3),np.uint8) + depth_out = np.zeros((SENSOR_H,SENSOR_W),np.uint8) + + + #Initial shift as done in the original projection + init_shift = 0; + img = np.zeros((height,width,3),np.uint8) + depth_img = np.zeros((height,width),np.uint8) + + if init_shift < 0: + offset = -1*init_shift + img[0:height,0:width-offset] = spher_rgb[0:height,offset:width] + img[0:height,width-offset:width] = spher_rgb[0:height,0:offset] + ## depth map + depth_img[0:height,0:width-offset] = spher_depth[0:height,offset:width] + depth_img[0:height,width-offset:width] = spher_depth[0:height,0:offset] + + else: + offset = init_shift + img[0:height,0:offset] = spher_rgb[0:height,width-offset:width] + img[0:height,offset:width] = spher_rgb[0:height,0:width-offset] + ## depth map + depth_img[0:height,0:offset] = spher_depth[0:height,width-offset:width] + depth_img[0:height,offset:width] = spher_depth[0:height,0:width-offset] + + PI = 3.141592 + + #For front image + x=1.0 + for i in range(0, SENSOR_H): + z=(float(i)/SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + + y=(float(j)/SENSOR_W * (-2.0 * side_range)) + side_range + r = np.sqrt(x*x+y*y+z*z) + theta = np.arccos(z/r) + + if x==0: + phi= 0.5*PI + else: + phi = np.arctan(y/x) + + a = int(theta / PI * height + 0.5) + b = width -1 - int(phi / (2*PI) * width + 0.5) + + if b < 0: + b = b+width + if b > (width-1): + b = b-width + + img_out[i,j] = img[a,b] + depth_out[i,j] = depth_img[a,b] + + # rgb perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Cubic_1.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((1, out_filename)) + # depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Depth_Cubic_1.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((1, out_depth_filename)) + ############################################################################################ + + #For left image + y = -1.0 + for i in range(0, SENSOR_H): + z = (float(i) / SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + x = (float(j) / SENSOR_W * (-2.0 * side_range)) + side_range + # x = (float(j)/SENSOR_W * (-2.0 )) + 1.0 + r = np.sqrt(x * x + y * y + z * z) + theta = np.arccos(z / r) + if x == 0: + phi = 0.5 * PI + else: + phi = np.arctan(y / x) + + if phi > 0: + phi = phi + PI + + a = int(theta / PI * height + 0.5) + b = width - 1 - int(phi / (2 * PI) * width + 0.5) + + if b < 0: + b = b + width + if b > (width - 1): + b = b - width + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Cubic_2.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((2, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Depth_Cubic_2.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((2, out_depth_filename)) + ############################################################################################# + + #For back image + x = -1.0 + for i in range(0, SENSOR_H): + z = (float(i) / SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + y = (float(j) / SENSOR_W * (2.0 * side_range)) - side_range + # y = (float(j)/SENSOR_W * (2.0)) + 1.0 + + r = np.sqrt(x * x + y * y + z * z) + theta = np.arccos(z / r) + if x == 0: + phi = 0.5 * PI + else: + phi = np.arctan(y / x) + + phi = phi + PI + + a = int(theta / PI * height + 0.5) + b = width - 1 - int(phi / (2 * PI) * width + 0.5) + + if b < 0: + b = b + width + if b > (width - 1): + b = b - width + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Cubic_3.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((3, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Depth_Cubic_3.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((3, out_depth_filename)) + ############################################################################################## + + + #For right image + y= 1.0 + for i in range(0, SENSOR_H): + z = (float(i) / SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + x = (float(j) / SENSOR_W * (2.0 * side_range)) - side_range + # x = (float(j)/SENSOR_W * (2.0)) + 1.0 + r = np.sqrt(x * x + y * y + z * z) + theta = np.arccos(z / r) + if x == 0: + phi = 0.5 * PI + else: + phi = np.arctan(y / x) + + if phi < 0: + phi = phi + PI + + a = int(theta / PI * height + 0.5) + b = width - 1 - int(phi / (2 * PI) * width + 0.5) + + if b < 0: + b = b + width + if b > (width - 1): + b = b - width + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Cubic_4.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((4, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Depth_Cubic_4.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((4, out_depth_filename)) + + ############################################################################################### + ''' + #For top image + z= 1.0 + for i in range(0, SENSOR_H): + x=(float(i)/SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + y=(float(j)/SENSOR_W * (-2.0 * side_range)) + side_range + + r = np.sqrt(x*x+y*y+z*z) + theta = np.arccos(z/r) + if x==0: + phi= 0.5*PI + else: + phi = np.arctan(y/x) + if i>= face_height/2: + phi=phi+PI + + a = int(theta / PI * height + 0.5) + b = width -1 - int(phi / (2*PI) * width + 0.5) + + if b < 0: + b = b+width + if b > (width-1): + b = b-width + if a<0: + a=0 + if a > height-1: + a=height-1 + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Cubic_5.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((5, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Depth_Cubic_5.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((5, out_depth_filename)) + ######################################################################### + + #For bottom image + z= -1.0 + for i in range(0, SENSOR_H): + x=(float(i)/SENSOR_H * (2.0)) - 1.0 + + for j in range(0, SENSOR_W): + y=(float(j)/SENSOR_W * (2.0 * side_range)) - side_range + + r = np.sqrt(x*x+y*y+z*z) + theta = np.arccos(z/r) + + if x==0: + phi= 0.5*PI + else: + phi = np.arctan(y/x) + if i<= face_height/2: + phi=phi+PI + + a = int(theta / PI * height + 0.5) + b = width -1 - int(phi / (2*PI) * width + 0.5) + + if b < 0: + b = b+width + if b > (width-1): + b = b-width + + if a<0: + a=0 + if a > height-1: + a=height-1 + + + o# Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Cubic_6.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((6, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_Depth_Cubic_6.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((6, out_depth_filename)) +''' +############################################################################################## + + return rgb_views , depth_views + + ''' + ############################################################ shift 45 to get the rest of the views ######################################################### + rotation = width//8 + #init_shift = int((-1)*width//4 - rotation) + init_shift = int(width//4 - rotation) + PI = 3.141592 + img = np.zeros((height,width,3),np.uint8) + depth_img = np.zeros((height,width),np.uint8) + + if init_shift < 0: + offset = -1*init_shift + img[0:height,0:width-offset] = spher_rgb[0:height,offset:width] + img[0:height,width-offset:width]= spher_rgb[0:height,0:offset] + ## depth map + depth_img[0:height,0:width-offset] = spher_depth[0:height,offset:width] + depth_img[0:height,width-offset:width]= spher_depth[0:height,0:offset] + + + else: + offset = init_shift + img[0:height,0:offset] = spher_rgb[0:height,width-offset:width] + img[0:height,offset:width] = spher_rgb[0:height,0:width-offset] + ## depth map + depth_img[0:height,0:offset] = spher_depth[0:height,width-offset:width] + depth_img[0:height,offset:width] = spher_depth[0:height,0:width-offset] + + #For front image + x = 1.0 + for i in range(0, SENSOR_H): + z = (float(i) / SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + y = (float(j) / SENSOR_W * (-2.0 * side_range)) + side_range + # y = (float(j)/SENSOR_W * (-2.0)) + 1.0 + r = np.sqrt(x * x + y * y + z * z) + theta = np.arccos(z / r) + if x == 0: + phi = 0.5 * PI + else: + phi = np.arctan(y / x) + + a = int(theta / PI * height + 0.5) + b = width - 1 - int(phi / (2 * PI) * width + 0.5) + + if b < 0: + b = b + width + if b > (width - 1): + b = b - width + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Cubic_1.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((1, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Depth_Cubic_1.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((1, out_depth_filename)) + + # For left image + y = -1.0 + for i in range(0, SENSOR_H): + z = (float(i) / SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + x = (float(j) / SENSOR_W * (-2.0 * side_range)) + side_range + # x = (float(j)/SENSOR_W * (-2.0)) + 1.0 + r = np.sqrt(x * x + y * y + z * z) + theta = np.arccos(z / r) + if x == 0: + phi = 0.5 * PI + else: + phi = np.arctan(y / x) + + if phi > 0: + phi = phi + PI + + a = int(theta / PI * height + 0.5) + b = width - 1 - int(phi / (2 * PI) * width + 0.5) + + if b < 0: + b = b + width + if b > (width - 1): + b = b - width + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Cubic_2.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((2, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Depth_Cubic_2.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((2, out_depth_filename)) + + # For back image + x = -1.0 + for i in range(0, SENSOR_H): + z = (float(i) / SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + y = (float(j) / SENSOR_W * (2.0 * side_range)) - side_range + # y = (float(j)/SENSOR_W * (2.0)) + 1.0 + r = np.sqrt(x * x + y * y + z * z) + theta = np.arccos(z / r) + if x == 0: + phi = 0.5 * PI + else: + phi = np.arctan(y / x) + + phi = phi + PI + + a = int(theta / PI * height + 0.5) + b = width - 1 - int(phi / (2 * PI) * width + 0.5) + + if b < 0: + b = b + width + if b > (width - 1): + b = b - width + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Cubic_3.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((3, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Depth_Cubic_3.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((3, out_depth_filename)) + + # For right image + y = 1.0 + for i in range(0, SENSOR_H): + z = (float(i) / SENSOR_H * (-2.0)) + 1.0 + + for j in range(0, SENSOR_W): + x = (float(j) / SENSOR_W * (2.0 * side_range)) - side_range + # x = (float(j)/SENSOR_W * (2.0)) + 1.0 + r = np.sqrt(x * x + y * y + z * z) + theta = np.arccos(z / r) + if x == 0: + phi = 0.5 * PI + else: + phi = np.arctan(y / x) + + if phi < 0: + phi = phi + PI + + a = int(theta / PI * height + 0.5) + b = width - 1 - int(phi / (2 * PI) * width + 0.5) + + if b < 0: + b = b + width + if b > (width - 1): + b = b - width + + img_out[i, j] = img[a, b] + depth_out[i, j] = depth_img[a, b] + + # Save RGB perspective + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Cubic_4.png' + cv2.imwrite(out_filename, img_out) + rgb_views.append((4, out_filename)) + + # Save depth perspective + out_depth_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}_shift_Depth_Cubic_4.png' + cv2.imwrite(out_depth_filename, depth_out) + depth_views.append((4, out_depth_filename)) + ############################################################################################### + return rgb_views, depth_views + ''' + +''' +def parse_arguments(): + global DATA_PATH, OUTPUT_PATH + + print("\nSemantic Scene Completion Inference from 360 depth maps\n") + + parser = argparse.ArgumentParser() + parser.add_argument("dataset", help="360 dataset dir", type=str) + parser.add_argument("depth_map", help="360 depth map", type=str) + parser.add_argument("rgb_file", help="rgb", type=str) + parser.add_argument("output", help="output file prefix", type=str) + + + args = parser.parse_args() + + + DATA_PATH = args.data_path + OUTPUT_PATH = args.output_path + + dataset = args.dataset + depth_map = os.path.join(DATA_PATH, dataset, args.depth_map) + rgb_file = os.path.join(DATA_PATH, dataset, args.rgb_file) + output = os.path.join(OUTPUT_PATH, args.output) + + fail = False + if not os.path.isfile(depth_map): + print("Depth map file not found:", depth_map) + fail = True + + if not os.path.isfile(rgb_file): + print("RGB file not found:", rgb_file ) + fail = True + + if fail: + print("Exiting...\n") + exit(0) + + if not os.path.isdir(OUTPUT_PATH): + os.makedirs(OUTPUT_PATH, exist_ok=True) + + print("360 depth map:", depth_map) + print("360 rgb: ", rgb_file) + print("Output prefix:", output) + print("") + + return depth_map, rgb_file, output, rgb_views, depth_views + +# Main Function +def Run(): + depth_map, rgb_file, output = parse_arguments() + dual_cubic_proj(depth_map, rgb_file, output) + + +if __name__ == '__main__': + Run() +''' +''' +################################################################################################################################################################# +import sys +from PIL import Image +from math import pi, sin, cos, tan, atan2, hypot, floor +from numpy import clip + +# get x,y,z coords from out image pixels coords +# i,j are pixel coords +# faceIdx is face number +# faceSize is edge length +def outImgToXYZ(i, j, faceIdx): + #a = 2.0 * float(i) / faceSize + #b = 2.0 * float(j) / faceSize + a = 2.0 * float(i) / SENSOR_W + b = 2.0 * float(j) / SENSOR_H + + if faceIdx == 0: # back + (x,y,z) = (-1.0, 1.0 - a, 1.0 - b) + elif faceIdx == 1: # left + (x,y,z) = (a - 1.0, -1.0, 1.0 - b) + elif faceIdx == 2: # front + (x,y,z) = (1.0, a - 1.0, 1.0 - b) + elif faceIdx == 3: # right + (x,y,z) = (1.0 - a, 1.0, 1.0 - b) + elif faceIdx == 4: # top + (x,y,z) = (b - 1.0, a - 1.0, 1.0) + elif faceIdx == 5: # bottom + (x,y,z) = (1.0 - b, a - 1.0, -1.0) + + return (x, y, z) + +# convert using an inverse transformation +def convertFace(imgIn, imgOut, faceIdx): + inSize = imgIn.size + outSize = imgOut.size + inPix = imgIn.load() + outPix = imgOut.load() + faceSize = outSize[0] + + for xOut in range(SENSOR_W): + for yOut in range(SENSOR_H): + (x,y,z) = outImgToXYZ(xOut, yOut, faceIdx) + theta = atan2(y,x) # range -pi to pi + r = hypot(x,y) + phi = atan2(z,r) # range -pi/2 to pi/2 + + # source img coords + uf = 0.5 * inSize[0] * (theta + pi) / pi + vf = 0.5 * inSize[0] * (pi/2 - phi) / pi + + # Use bilinear interpolation between the four surrounding pixels + ui = floor(uf) # coord of pixel to bottom left + vi = floor(vf) + u2 = ui+1 # coords of pixel to top right + v2 = vi+1 + mu = uf-ui # fraction of way across pixel + nu = vf-vi + + # Pixel values of four corners + A = inPix[ui % inSize[0], clip(vi, 0, inSize[1]-1)] + B = inPix[u2 % inSize[0], clip(vi, 0, inSize[1]-1)] + C = inPix[ui % inSize[0], clip(v2, 0, inSize[1]-1)] + D = inPix[u2 % inSize[0], clip(v2, 0, inSize[1]-1)] + + # interpolate + (r,g,b) = ( + A[0]*(1-mu)*(1-nu) + B[0]*(mu)*(1-nu) + C[0]*(1-mu)*nu+D[0]*mu*nu, + A[1]*(1-mu)*(1-nu) + B[1]*(mu)*(1-nu) + C[1]*(1-mu)*nu+D[1]*mu*nu, + A[2]*(1-mu)*(1-nu) + B[2]*(mu)*(1-nu) + C[2]*(1-mu)*nu+D[2]*mu*nu ) + + outPix[xOut, yOut] = (int(round(r)), int(round(g)), int(round(b))) + + +def spher_cubic_proj(depth_file, rgb_file, out_prefix): + + spher_rgb = cv2.imread(rgb_file, cv2.IMREAD_COLOR) + spher_depth = cv2.imread(depth_file, cv2.IMREAD_ANYDEPTH) + print('spher_rgb shape', spher_rgb.shape) + print('spher_depth shape', spher_depth.shape) + height, width, channels = spher_rgb.shape + rgb_views = [] + depth_views = [] + imgIn = Image.open(rgb_file) + inSize = imgIn.size + print (inSize) + faceSize = inSize[0] // 4 + #components = rgb_file.rsplit('.', 2) + + FACE_NAMES = { + #0: 'back', #cubic3 + #1: 'left', # cubic2 + #2: 'front', # cubic1 + #3: 'right', # cubic4 + #4: 'top', + #5: 'bottom' + + 0: 'Cubic_1_front', # front + 1: 'Cubic_2_left', # left + 2: 'Cubic_3_right', # back + 3: 'Cubic_4_back', # right + 4: 'top', + 5: 'bottom' + } + + if not os.path.exists('./splitted_spher'): + os.makedirs('./splitted_spher') + + for face in range(6): + imgOut = Image.new("RGB", (SENSOR_W, SENSOR_H), "black") + convertFace(imgIn, imgOut, face) # depth_file, rgb_file, out_prefix + out_filename = f'./splitted_spher/{out_prefix.rsplit("/", 1)[-1]}' + imgOut.save(out_filename+"_" + FACE_NAMES[face] + ".png") + rgb_views.append((face+1, out_filename)) + + return rgb_views, depth_views +''' + \ No newline at end of file diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/visual_utils.py b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/visual_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..a0f4efa8a94f46af7bcef6134b543fbd698bb664 --- /dev/null +++ b/Mona-SSC/Mona-SSC/MDBNet360_GDP/utils/visual_utils.py @@ -0,0 +1,589 @@ +# Based on: https://gitlab.com/UnBVision/edgenet360/-/blob/master/lib_edgenet360/file_utils.py?ref_type=heads + +import numpy as np +from sklearn.utils import shuffle +from fnmatch import fnmatch +import os +import threading + + +def get_file_prefixes_from_path(data_path, criteria="*.bin"): + prefixes = [] + + for path, subdirs, files in os.walk(data_path): + #print(path) + #print(subdirs) + for name in files: + if fnmatch(name, criteria): + prefixes.append(os.path.join(path, name)[:-4]) + + prefixes.sort() + + return prefixes + + +class threadsafe_generator(object): + """Takes an iterator/generator and makes it thread-safe by + serializing call to the `next` method of given iterator/generator. + """ + def __init__(self, gen): + self.gen = gen + self.lock = threading.Lock() + + def __iter__(self): + return self + + def __next__(self): + with self.lock: + return self.gen.__next__() + + +def threadsafe(f): + """A decorator that takes a generator function and makes it thread-safe. + """ + def g(*a, **kw): + return threadsafe_generator(f(*a, **kw)) + return g + + +@threadsafe +def ftsdf_generator(file_prefixes, batch_size=4, shuff=False, shape=(240, 144, 240), down_scale = 4): # write the definition of your data generator + + while True: + x_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) + rgb_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 3)) + y_batch = np.zeros((batch_size, shape[0] // down_scale, shape[1] // down_scale, shape[2] // down_scale, 12)) + w_batch = np.zeros((batch_size, shape[0] // down_scale, shape[1] // down_scale, shape[2] // down_scale)) + batch_count = 0 + if shuff: + file_prefixes_s = shuffle(file_prefixes) + else: + file_prefixes_s = file_prefixes + + for count, file_prefix in enumerate(file_prefixes_s): + + + vox_tsdf, vox_rgb, segmentation_label, vox_weights = process(file_prefix, voxel_shape=(240, 144, 240), down_scale=4) + + x_batch[batch_count] = vox_tsdf.reshape((shape[0], shape[1], shape[2],1)) + rgb_batch[batch_count] = vox_rgb.reshape((shape[0], shape[1], shape[2],3)) + y_batch[batch_count] = to_categorical(segmentation_label.reshape((60, 36, 60,1)), num_classes=12) + w_batch[batch_count] = vox_weights.reshape((60, 36, 60)) + batch_count += 1 + if batch_count == batch_size: + yield [x_batch, rgb_batch], y_batch, w_batch + x_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) #channels last + rgb_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 3)) #channels last + y_batch = np.zeros((batch_size, shape[0] // down_scale, shape[1] // down_scale, shape[2] // down_scale, 12)) + w_batch = np.zeros((batch_size, shape[0]//down_scale, shape[1]//down_scale, shape[2]//down_scale)) + batch_count = 0 + + if(batch_count > 0): + yield [x_batch[:batch_count], rgb_batch[:batch_count]], y_batch[:batch_count], w_batch[:batch_count] + + +@threadsafe +def preproc_generator(file_prefixes, batch_size=4, shuff=False, aug=False, vol=False, shape=(240, 144, 240), down_scale = 4, type="rgb"): # write the definition of your data generator + + down_shape = (shape[0] // down_scale, shape[1] // down_scale, shape[2] // down_scale) + + while True: + x_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) + if type == "rgb": + rgb_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 3)) + elif type == "edges": + edges_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) + y_batch = np.zeros((batch_size, down_shape[0], down_shape[1], down_shape[2], 12)) + if vol: + vol_batch = np.zeros((batch_size, down_shape[0], down_shape[1], down_shape[2])) + batch_count = 0 + if shuff: + file_prefixes_s = shuffle(file_prefixes) + else: + file_prefixes_s = file_prefixes + + for count, file_prefix in enumerate(file_prefixes_s): + + npz_file = file_prefix + '.npz' + loaded = np.load(npz_file) + + #print(file_prefix) + + vox_tsdf = loaded['tsdf'] + if type == "rgb": + vox_rgb = loaded['rgb'] + elif type == "edges": + vox_edges = loaded['edges'] + vox_label = loaded['lbl'] + vox_weights = loaded['weights'] + if vol: + vox_vol = loaded['vol'] + + x_batch[batch_count] = vox_tsdf + if vol: + vol_batch[batch_count] = vox_vol + + if aug: + + aug_v = np.random.normal(loc=1, scale=0.05, size=3) + + else: + aug_v=np.array([1.,1.,1.]) + + if type == "rgb": + rgb_batch[batch_count] = np.clip(vox_rgb * aug_v, 0., 1.) + elif type == "edges": + edges_batch[batch_count] = vox_edges + + labels = to_categorical(vox_label, num_classes=12) + weights = np.repeat(vox_weights,12,axis=-1).reshape((down_shape[0], down_shape[1], down_shape[2], 12)) + y_batch[batch_count] = labels * (weights+1) + batch_count += 1 + if batch_count == batch_size: + if type == "rgb": + if vol: + yield [x_batch, rgb_batch], y_batch, vol_batch + else: + yield [x_batch, rgb_batch], y_batch + elif type == "edges": + if vol: + yield [x_batch, edges_batch], y_batch, vol_batch + else: + yield [x_batch, edges_batch], y_batch + elif type == "depth": + if vol: + yield x_batch, y_batch, vol_batch + else: + yield x_batch, y_batch + + x_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) #channels last + if type == "rgb": + rgb_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 3)) + elif type == "edges": + edges_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) + y_batch = np.zeros((batch_size, down_shape[0], down_shape[1], down_shape[2], 12)) + if vol: + vol_batch = np.zeros((batch_size, down_shape[0], down_shape[1], down_shape[2])) + batch_count = 0 + + if batch_count > 0: + if type == "rgb": + if vol: + yield [x_batch[:batch_count], rgb_batch[:batch_count]], y_batch[:batch_count],vol_batch[:batch_count] + else: + yield [x_batch[:batch_count], rgb_batch[:batch_count]], y_batch[:batch_count] + elif type == "edges": + if vol: + yield [x_batch[:batch_count], edges_batch[:batch_count]], y_batch[:batch_count],vol_batch[:batch_count] + else: + yield [x_batch[:batch_count], edges_batch[:batch_count]], y_batch[:batch_count] + elif type == "depth": + if vol: + yield x_batch[:batch_count], y_batch[:batch_count],vol_batch[:batch_count] + else: + yield x_batch[:batch_count], y_batch[:batch_count] + + +@threadsafe +def evaluate_generator(file_prefixes, batch_size=4, shuff=False, shape=(240, 144, 240), down_scale = 4): # write the definition of your data generator + + while True: + x_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) + y_batch = np.zeros((batch_size, shape[0] // down_scale, shape[1] // down_scale, shape[2] // down_scale, 12)) + f_batch = np.zeros((batch_size, shape[0] // down_scale, shape[1] // down_scale, shape[2] // down_scale),dtype=np.int32) + batch_count = 0 + if shuff: + file_prefixes_s = shuffle(file_prefixes) + else: + file_prefixes_s = file_prefixes + + for count, file_prefix in enumerate(file_prefixes_s): + + + vox_tsdf, segmentation_label, vox_flags = process_evaluate(file_prefix, voxel_shape=(240, 144, 240), down_scale=4) + + x_batch[batch_count] = vox_tsdf.reshape((shape[0], shape[1], shape[2],1)) + y_batch[batch_count] = to_categorical(segmentation_label.reshape((60, 36, 60,1)), num_classes=12) + f_batch[batch_count] = vox_flags.reshape((60, 36, 60)) + batch_count += 1 + if batch_count == batch_size: + yield x_batch, y_batch, f_batch + x_batch = np.zeros((batch_size, shape[0], shape[1], shape[2], 1)) #channels last + y_batch = np.zeros((batch_size, shape[0] // down_scale, shape[1] // down_scale, shape[2] // down_scale, 12)) + f_batch = np.zeros((batch_size, shape[0]//down_scale, shape[1]//down_scale, shape[2]//down_scale),dtype=np.int32) + batch_count = 0 + + if(batch_count > 0): + yield x_batch[:batch_count], y_batch[:batch_count],f_batch[:batch_count] + +def voxel_export(name, vox, shape, tsdf_range=None, sample=None): + + from array import array + import struct + import random + + + + + vox = vox.reshape(shape) + + coord_x=array('i') + coord_y=array('i') + coord_z=array('i') + voxel_v=array('f') + + count = 0 + + for x in range(shape[0]): + for y in range (shape[1]): + for z in range(shape[2]): + if ((tsdf_range is None) and (vox[z,y,x]!=0)) or \ + ((not tsdf_range is None) and ((vox[z,y,x]<=tsdf_range[0] or vox[z,y,x]>=tsdf_range[1]) and vox[z,y,x]!=1)): + if sample is None or sample > random.random(): + coord_x.append(x) + coord_y.append(y) + coord_z.append(z) + voxel_v.append(vox[z,y,x]) + count += 1 + f = open(name, 'wb') + f.write(struct.pack("i", count)) + f.write(struct.pack(str(count)+"i", *coord_x)) + f.write(struct.pack(str(count)+"i", *coord_y)) + f.write(struct.pack(str(count)+"i", *coord_z)) + f.write(struct.pack(str(count)+"f", *voxel_v)) + f.close() + + return count + + +def rgb_voxel_export(name, vox, shape, sample=None): + + from array import array + import struct + import random + + + + + vox = vox.reshape(shape) + + coord_x=array('i') + coord_y=array('i') + coord_z=array('i') + voxel_r=array('f') + voxel_g=array('f') + voxel_b=array('f') + + count = 0 + + for x in range(shape[0]): + for y in range (shape[1]): + for z in range(shape[2]): + if (vox[x,y,z,0]>0) or (vox[x,y,z,1]>0) or (vox[x,y,z,2]) > 0: + if sample is None or sample > random.random(): + coord_x.append(x) + coord_y.append(y) + coord_z.append(z) + voxel_r.append(vox[x,y,z,0]/255) + voxel_g.append(vox[x,y,z,1]/255) + voxel_b.append(vox[x,y,z,2]/255) + count += 1 + print("saving...") + f = open(name, 'wb') + f.write(struct.pack("i", count)) + f.write(struct.pack(str(count)+"i", *coord_x)) + f.write(struct.pack(str(count)+"i", *coord_y)) + f.write(struct.pack(str(count)+"i", *coord_z)) + f.write(struct.pack(str(count)+"f", *voxel_r)) + f.write(struct.pack(str(count)+"f", *voxel_g)) + f.write(struct.pack(str(count)+"f", *voxel_b)) + f.close() + + print(count, "done...") + + + +def prediction_export(name, vox, weights, shape, tsdf_range=None): + + from array import array + import struct + + + + vox = vox.reshape(shape) + + coord_x=array('i') + coord_y=array('i') + coord_z=array('i') + voxel_v=array('f') + + count = 0 + + for x in range(shape[0]): + for y in range (shape[1]): + for z in range(shape[2]): + if ((vox[x,y,z]!=0) and (weights[x,y,z]!=0)): + coord_x.append(x) + coord_y.append(y) + coord_z.append(z) + voxel_v.append(vox[x,y,z]) + count += 1 + print("saving...") + f = open(name, 'wb') + f.write(struct.pack("i", count)) + f.write(struct.pack(str(count)+"i", *coord_x)) + f.write(struct.pack(str(count)+"i", *coord_y)) + f.write(struct.pack(str(count)+"i", *coord_z)) + f.write(struct.pack(str(count)+"f", *voxel_v)) + f.close() + + print(count, "done...") + +class_colors = [ + (0.1, 0.1, 0.1), + (0.0649613, 0.467197, 0.0667303), + (0.1, 0.847035, 0.1), + (0.0644802, 0.646941, 0.774265), + (0.131518, 0.273524, 0.548847), + (1, 0.813553, 0.0392201), + (1, 0.490452, 0.0624932), + (0.657877, 0.0505005, 1), + (0.0363214, 0.0959549, 0.548847), + (0.316852, 0.548847, 0.186899), + (0.548847, 0.143381, 0.0045568), + (1, 0.241096, 0.718126) + ] + +class_names = ["empty", "ceiling", "floor", "wall", "window", "chair", "bed", "sofa", + "table", "tvs", "furniture", "objects"] + + +def write_header(obj_file, mtl_file, name): + obj_file.write("# MDBNet360 Wavefront obj exporter v1.0\n") + obj_file.write("mtllib %s.mtl\n" % os.path.basename(name)) + obj_file.write("o Cube\n") + + mtl_file.write("# MDBNet360 Wavefront obj exporter v1.0\n") + # Blender MTL File: 'DWRC1.blend' + # Material Count: 11 + + +def write_vertice(obj_file, x, y, z, cx, cy, cz, v_unit): + vu = v_unit * 4 + obj_file.write("v %8.6f %8.6f %8.6f\n" %((x-cx)*vu, (y-cy)*vu, (z-cz)*vu)) + +def write_vertice_normals(obj_file): + obj_file.write("vn -1.000000 0.000000 0.000000\n") + obj_file.write("vn 0.000000 0.000000 -1.000000\n") + obj_file.write("vn 1.000000 0.000000 0.000000\n") + obj_file.write("vn 0.000000 0.000000 1.000000\n") + obj_file.write("vn 0.000000 -1.000000 0.000000\n") + obj_file.write("vn 0.000000 1.000000 0.000000\n") + + +def write_mtl_faces(obj_file, mtl_file, mtl_faces_list, cl, triangular): + obj_file.write("g %s\n" % class_names[cl]) + obj_file.write("usemtl %s\n" % class_names[cl]) + #obj_file.write("s off\n") + mtl_file.write("newmtl %s\n" % class_names[cl]) + + mtl_file.write("Ns 96.078431\n") + mtl_file.write("Ka 1.000000 1.000000 1.000000\n") + mtl_file.write("Kd %8.6f %8.6f %8.6f\n" % (class_colors[cl][0], class_colors[cl][1], class_colors[cl][2] ) ) + mtl_file.write("Ks 0.500000 0.500000 0.500000\n") + mtl_file.write("Ke 0.000000 0.000000 0.000000\n") + mtl_file.write("Ni 1.000000\n") + mtl_file.write("d 1.000000\n") + mtl_file.write("illum 2\n") + + + if not triangular: + for face_vertices in mtl_faces_list: + + obj_file.write("f ") + obj_file.write("%d//%d %d//%d %d//%d %d//%d" % ( + face_vertices[1]+1, face_vertices[0], + face_vertices[2]+1, face_vertices[0], + face_vertices[3]+1, face_vertices[0], + face_vertices[4]+1, face_vertices[0], + )) + obj_file.write("\n") + else: + for face_vertices in mtl_faces_list: + + obj_file.write("f ") + obj_file.write("%d//%d %d//%d %d//%d" % ( + face_vertices[1]+1, face_vertices[0], + face_vertices[2]+1, face_vertices[0], + face_vertices[3]+1, face_vertices[0], + )) + obj_file.write("\n") + + +def obj_export(name, vox, shape, camx, camy, camz, v_unit, include_top=False, triangular=False, inner_faces=True): + + num_classes=len(class_names) + + sx, sy, sz = vox.shape + + + _vox = np.ones((sx+2,sy+2,sz+2), dtype=np.uint8)*255 + _vox[1:-1,1:-1,1:-1] = vox + + cx, cy, cz = sx, sy, sz + ''' + _vox = np.ones((sx+2,sy+2,sz+2), dtype=np.uint8)*255 + _vox[1:-1,1:-1,1:-1] = vox + + cx, cy, cz = int(sx//2), int(camy//(v_unit*4)), int(sz//2) + ''' + vox_ctrl = np.ones((sx+1, sy+1, sz+1), dtype=np.int32) * -1 + mtl_faces_list =[None] * num_classes + + num_vertices = 0 + + with open(name+".obj", 'w') as obj_file, open(name+".mtl", 'w') as mtl_file: + + write_header(obj_file, mtl_file, name) + + for x in range(sx): + for y in range(sy): + if not include_top and y>26: + continue + for z in range(sz): + mtl = int(vox[x,y,z]) + if mtl == 0 or mtl==255: + continue + for vx in range(2): + for vy in range(2): + for vz in range(2): + if vox_ctrl[x+vx, y+vy, z+vz] == -1: + vox_ctrl[x + vx, y + vy, z + vz] = num_vertices + num_vertices += 1 + write_vertice(obj_file, x+vx, y+vy, z+vz, cx, cy, cz, v_unit) + if mtl_faces_list[mtl] is None: + mtl_faces_list[mtl] = [] + + if inner_faces: + + if triangular: + + mtl_faces_list[mtl].extend([ + [1, vox_ctrl[x+0, y+1, z+1], vox_ctrl[x+0, y+1, z+0], vox_ctrl[x+0, y+0, z+1]], #OK + [1, vox_ctrl[x+0, y+1, z+0], vox_ctrl[x+0, y+0, z+0], vox_ctrl[x+0, y+0, z+1]], #OK + + [2, vox_ctrl[x+0, y+1, z+0], vox_ctrl[x+1, y+1, z+0], vox_ctrl[x+0, y+0, z+0]], #OK + [2, vox_ctrl[x+1, y+1, z+0], vox_ctrl[x+1, y+0, z+0], vox_ctrl[x+0, y+0, z+0]], #OK + + [3, vox_ctrl[x+1, y+1, z+0], vox_ctrl[x+1, y+1, z+1], vox_ctrl[x+1, y+0, z+0]], #OK + [3, vox_ctrl[x+1, y+1, z+1], vox_ctrl[x+1, y+0, z+1], vox_ctrl[x+1, y+0, z+0]], #OK + + [4, vox_ctrl[x+1, y+1, z+1], vox_ctrl[x+0, y+1, z+1], vox_ctrl[x+1, y+0, z+1]], #OK + [4, vox_ctrl[x+0, y+1, z+1], vox_ctrl[x+0, y+0, z+1], vox_ctrl[x+1, y+0, z+1]], #OK + + [5, vox_ctrl[x+0, y+0, z+1], vox_ctrl[x+0, y+0, z+0], vox_ctrl[x+1, y+0, z+1]], #OK + [5, vox_ctrl[x+0, y+0, z+0], vox_ctrl[x+1, y+0, z+0], vox_ctrl[x+1, y+0, z+1]], #OK + + [6, vox_ctrl[x+0, y+1, z+0], vox_ctrl[x+0, y+1, z+1], vox_ctrl[x+1, y+1, z+0]], #OK + [6, vox_ctrl[x+0, y+1, z+1], vox_ctrl[x+1, y+1, z+1], vox_ctrl[x+1, y+1, z+0]] #OK + ]) + + else: + + mtl_faces_list[mtl].extend([ + [1, vox_ctrl[x + 0, y + 1, z + 1], vox_ctrl[x + 0, y + 1, z + 0], + vox_ctrl[x + 0, y + 0, z + 0], vox_ctrl[x + 0, y + 0, z + 1]], # OK + [2, vox_ctrl[x + 0, y + 1, z + 0], vox_ctrl[x + 1, y + 1, z + 0], + vox_ctrl[x + 1, y + 0, z + 0], vox_ctrl[x + 0, y + 0, z + 0]], # OK + [3, vox_ctrl[x + 1, y + 1, z + 0], vox_ctrl[x + 1, y + 1, z + 1], + vox_ctrl[x + 1, y + 0, z + 1], vox_ctrl[x + 1, y + 0, z + 0]], # OK + [4, vox_ctrl[x + 1, y + 1, z + 1], vox_ctrl[x + 0, y + 1, z + 1], + vox_ctrl[x + 0, y + 0, z + 1], vox_ctrl[x + 1, y + 0, z + 1]], # OK + [5, vox_ctrl[x + 0, y + 0, z + 1], vox_ctrl[x + 0, y + 0, z + 0], + vox_ctrl[x + 1, y + 0, z + 0], vox_ctrl[x + 1, y + 0, z + 1]], # OK + [6, vox_ctrl[x + 0, y + 1, z + 0], vox_ctrl[x + 0, y + 1, z + 1], + vox_ctrl[x + 1, y + 1, z + 1], vox_ctrl[x + 1, y + 1, z + 0]] # OK + ]) + else: + _x, _y, _z = x+1, y+1, z+1 + if triangular: + + if _vox[_x - 1,_y,_z] != _vox[_x, _y, _z] and _vox[_x-1,_y,_z]!=255: + mtl_faces_list[mtl].extend([ + [1, vox_ctrl[x + 0, y + 1, z + 1], vox_ctrl[x + 0, y + 1, z + 0], + vox_ctrl[x + 0, y + 0, z + 1]], # OK + [1, vox_ctrl[x + 0, y + 1, z + 0], vox_ctrl[x + 0, y + 0, z + 0], + vox_ctrl[x + 0, y + 0, z + 1]]]) # OK + + if _vox[_x, _y, _z-1] != _vox[_x, _y, _z] and _vox[_x, _y, _z-1]!=255: + mtl_faces_list[mtl].extend([ + [2, vox_ctrl[x + 0, y + 1, z + 0], vox_ctrl[x + 1, y + 1, z + 0], + vox_ctrl[x + 0, y + 0, z + 0]], # OK + [2, vox_ctrl[x + 1, y + 1, z + 0], vox_ctrl[x + 1, y + 0, z + 0], + vox_ctrl[x + 0, y + 0, z + 0]]]) # OK + + if _vox[_x + 1, _y, _z] != _vox[_x, _y, _z] and _vox[_x + 1, _y, _z]!=255: + mtl_faces_list[mtl].extend([ + [3, vox_ctrl[x + 1, y + 1, z + 0], vox_ctrl[x + 1, y + 1, z + 1], + vox_ctrl[x + 1, y + 0, z + 0]], # OK + [3, vox_ctrl[x + 1, y + 1, z + 1], vox_ctrl[x + 1, y + 0, z + 1], + vox_ctrl[x + 1, y + 0, z + 0]]]) # OK + + if _vox[_x, _y, _z + 1] != _vox[_x, _y, _z] and _vox[_x, _y, _z + 1]!=255: + mtl_faces_list[mtl].extend([ + [4, vox_ctrl[x + 1, y + 1, z + 1], vox_ctrl[x + 0, y + 1, z + 1], + vox_ctrl[x + 1, y + 0, z + 1]], # OK + [4, vox_ctrl[x + 0, y + 1, z + 1], vox_ctrl[x + 0, y + 0, z + 1], + vox_ctrl[x + 1, y + 0, z + 1]]]) # OK + + if _vox[_x, _y-1, _z] != _vox[_x, _y, _z] and _vox[_x, _y-1, _z]!=255: + mtl_faces_list[mtl].extend([ + [5, vox_ctrl[x + 0, y + 0, z + 1], vox_ctrl[x + 0, y + 0, z + 0], + vox_ctrl[x + 1, y + 0, z + 1]], # OK + [5, vox_ctrl[x + 0, y + 0, z + 0], vox_ctrl[x + 1, y + 0, z + 0], + vox_ctrl[x + 1, y + 0, z + 1]]]) # OK + + if _vox[_x, _y + 1, _z] != _vox[_x, _y, _z] and _vox[_x, _y + 1, _z]!=255: + mtl_faces_list[mtl].extend([ + [6, vox_ctrl[x + 0, y + 1, z + 0], vox_ctrl[x + 0, y + 1, z + 1], + vox_ctrl[x + 1, y + 1, z + 0]], # OK + [6, vox_ctrl[x + 0, y + 1, z + 1], vox_ctrl[x + 1, y + 1, z + 1], + vox_ctrl[x + 1, y + 1, z + 0]]]) # OK + + else: + + if _vox[_x - 1, _y, _z] != _vox[_x, _y, _z] and _vox[_x - 1, _y, _z]!=255: + mtl_faces_list[mtl].extend([ + [1, vox_ctrl[x + 0, y + 1, z + 1], vox_ctrl[x + 0, y + 1, z + 0], + vox_ctrl[x + 0, y + 0, z + 0], vox_ctrl[x + 0, y + 0, z + 1]]]) # OK + if _vox[_x, _y, _z - 1] != _vox[_x, _y, _z] and _vox[_x, _y, _z - 1]!=255: + mtl_faces_list[mtl].extend([ + [2, vox_ctrl[x + 0, y + 1, z + 0], vox_ctrl[x + 1, y + 1, z + 0], + vox_ctrl[x + 1, y + 0, z + 0], vox_ctrl[x + 0, y + 0, z + 0]]]) # OK + if _vox[_x + 1, _y, _z] != _vox[_x, _y, _z] and _vox[_x + 1, _y, _z]!=255: + mtl_faces_list[mtl].extend([ + [3, vox_ctrl[x + 1, y + 1, z + 0], vox_ctrl[x + 1, y + 1, z + 1], + vox_ctrl[x + 1, y + 0, z + 1], vox_ctrl[x + 1, y + 0, z + 0]]]) # OK + if _vox[_x, _y, _z + 1] != _vox[_x, _y, _z] and _vox[_x, _y, _z + 1]!=255: + mtl_faces_list[mtl].extend([ + [4, vox_ctrl[x + 1, y + 1, z + 1], vox_ctrl[x + 0, y + 1, z + 1], + vox_ctrl[x + 0, y + 0, z + 1], vox_ctrl[x + 1, y + 0, z + 1]]]) # OK + if _vox[_x, _y - 1, _z] != _vox[_x, _y, _z] and _vox[_x, _y - 1, _z]!=255: + mtl_faces_list[mtl].extend([ + [5, vox_ctrl[x + 0, y + 0, z + 1], vox_ctrl[x + 0, y + 0, z + 0], + vox_ctrl[x + 1, y + 0, z + 0], vox_ctrl[x + 1, y + 0, z + 1]]]) # OK + if _vox[_x, _y + 1, _z] != _vox[_x, _y, _z] and _vox[_x, _y + 1, _z]!=255: + mtl_faces_list[mtl].extend([ + [6, vox_ctrl[x + 0, y + 1, z + 0], vox_ctrl[x + 0, y + 1, z + 1], + vox_ctrl[x + 1, y + 1, z + 1], vox_ctrl[x + 1, y + 1, z + 0]]]) # OK + + write_vertice_normals(obj_file) + + for mtl in range(num_classes): + if not mtl_faces_list[mtl] is None: + write_mtl_faces(obj_file, mtl_file, mtl_faces_list[mtl], mtl, triangular) + + + + return + diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/weights/2D_pretrained_late_tanh_identity_fold1_2024-01-26.pth b/Mona-SSC/Mona-SSC/MDBNet360_GDP/weights/2D_pretrained_late_tanh_identity_fold1_2024-01-26.pth new file mode 100644 index 0000000000000000000000000000000000000000..2b6e0c855e641fd78aba8934689c080e8b5932c4 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/weights/2D_pretrained_late_tanh_identity_fold1_2024-01-26.pth differ diff --git a/Mona-SSC/Mona-SSC/MDBNet360_GDP/weights/ResUNet_rgb_late_tanh_identity_fold1_2024-01-26.pth b/Mona-SSC/Mona-SSC/MDBNet360_GDP/weights/ResUNet_rgb_late_tanh_identity_fold1_2024-01-26.pth new file mode 100644 index 0000000000000000000000000000000000000000..3bc3bf15842eb01f8c7d59d0d0fe84fd8cf4e2d6 Binary files /dev/null and b/Mona-SSC/Mona-SSC/MDBNet360_GDP/weights/ResUNet_rgb_late_tanh_identity_fold1_2024-01-26.pth differ