Skip to content

Commit

Permalink
Merge pull request #55 from davircarvalho/master
Browse files Browse the repository at this point in the history
add SOFAresample function
  • Loading branch information
isfmiho committed Sep 29, 2022
2 parents 4eb9df7 + 1c64b76 commit 8a781cb
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
75 changes: 75 additions & 0 deletions SOFAtoolbox/SOFAresample.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
function Obj = SOFAresample(Obj, Fs, scale)
% Signal resampling
%
% Description:
% This function modifies the input SOFA object
% to a specified sampling rate
%
% Usage: Obj = SOFAresample(Obj, Fs)
%
% Input parameters:
% Obj: SOFA object with SimpleFreeFieldHRIR convention.
% Fs: Desired output sampling rate
% scale: Wheter or not to scale the output to have a similar
% output total energy as the input.
%
% Output arguments:
% Obj: SOFA object with SimpleFreeFieldHRIR convention.

% #Author: Davi R. Carvalho

%% parse inputs
if nargin < 3
scale = true;
elseif nargin == 3
scale = boolean(scale);
end

%% Process
Obj = SOFAconvertConventions(Obj);
Fs_orig = Obj.Data.SamplingRate;
IR = resample_this(Obj.Data.IR, Fs_orig, Fs, scale);

%% Output
Obj.Data.IR = IR;
Obj.Data.SamplingRate = Fs;
Obj = SOFAupdateDimensions(Obj);
end

% --------------------------------------------------------------------------
function IR = resample_this(X, Fs_in, Fs_out, scale)
[p,q] = rat(Fs_out / Fs_in, 0.0001);
normFc = .965 / max(p,q);
order = 256 * max(p,q);
beta = 12;
%%% Create a filter via Least-square linear-phase FIR filter design
lpFilt = firls(order, [0 normFc normFc 1],[1 1 0 0]);
lpFilt = lpFilt .* kaiser(order+1,beta)';
lpFilt = lpFilt / sum(lpFilt);
lpFilt = p * lpFilt;

% Initialize output matrix
N_pos = size(X, 1);
N_ch = size(X, 2);
N_samples = ceil((Fs_out/Fs_in) * size(X, 3)); % length after resample
IR=zeros(N_pos, N_ch, N_samples);

% Actual Resample
for k = 1:N_pos
for l = 1:N_ch
IR(k, l, :) = resample(squeeze(X(k,l,:)), p, q, lpFilt);
end
end

% check scaling
if scale
IR = IR.* q/p;
end

% make sure signal length is not odd
% if rem(size(IR,3), 2) ~= 0
% IR(:,:,end) = [];
% end
end


66 changes: 66 additions & 0 deletions SOFAtoolbox/demos/demo_SOFAresample.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
% load Obj and resample it
%
% #Author: Davi Carvalho
%
% 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
Fs_target = 96000;
Obj_out = SOFAresample(Obj, Fs_target);

%% general properties
fs = Obj.Data.SamplingRate;
% HRIRs
IR = shiftdim(Obj.Data.IR, 2);
IR_out = shiftdim(Obj_out.Data.IR, 2);
% Number of samples
N = size(IR, 1);
N_out = size(IR_out, 1);
% Time vector
tx = 0:1/fs:(N-1)/fs;
tx_out = 0:1/Fs_target:(N_out-1)/Fs_target;
% Frequency vector
freq = (0:N_out/2-1)*fs/N_out;
freq_out = (0:N_out/2-1)*Fs_target/N_out;

%% PLOTS
ch = 1; % ear
pos = 1; % position index

%%% Plot time
figure()
plot(tx, IR(:,pos,ch)); hold on
plot(tx_out, IR_out(:, pos, ch), '--','linewidth', 1.3); hold off
xlim([0, min(N_out, N)])
legend('original', 'resampled', 'location', 'best')
xlabel('Time (ms)')
axis tight

%%% Plot freq
figure()
ori = mag2db(abs(fft(IR(:,pos,ch), N_out)));
out = mag2db(abs(fft(IR_out(:,pos,ch))));
semilogx(freq, ori(1:N_out/2)); hold on
semilogx(freq_out, out(1:N_out/2), '--','linewidth', 1.3); hold off
legend('original', 'resampled', 'location', 'best')
xlabel('Frequency (Hz)')
ylabel('Amplitude (dB)')
axis tight






0 comments on commit 8a781cb

Please sign in to comment.