Commit 4119f4da authored by Archit Tamarapu's avatar Archit Tamarapu
Browse files

revert scripts related updates, moved to MR !1008

parent 204a38f3
Loading
Loading
Loading
Loading
Loading
+0 −117
Original line number Diff line number Diff line
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
%   (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
%   Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
%   Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
%   Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
%   contributors to this repository. All Rights Reserved.
%
%   This software is protected by copyright law and by international treaties.
%   The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
%   Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
%   Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
%   Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
%   contributors to this repository retain full ownership rights in their respective contributions in
%   the software. This notice grants no license of any kind, including but not limited to patent
%   license, nor is any license granted by implication, estoppel or otherwise.
%
%   Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
%   contributions.
%
%   This software is provided "AS IS", without any express or implied warranties. The software is in the
%   development stage. It is intended exclusively for experts who have experience with such software and
%   solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
%   and fitness for a particular purpose are hereby disclaimed and excluded.
%
%   Any dispute, controversy or claim arising under or in relation to providing this software shall be
%   submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
%   accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
%   the United Nations Convention on Contracts on the International Sales of Goods.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function IR_cldfb = SD_2_ROM( rom_c_file, sofa_file)
% SD_2_ROM( rom_c_file, sofa_file, ambisonics_order, hrir_length )
%
% Derived from SHD_2_ROM.m
% - loads sphere-sampled Head Related Impulse Responses (HRIRs) given in sofa_file 
% - converts SD HRIRs to Complex Low Delay Filter Bank (CLDFB) domain using fir_to_cldfb_fir.m
% - writes CLDFB HRIRs to c-code ROM tables.
[thispath,~,~] = fileparts(mfilename('fullpath'));
thispath = [thispath,filesep];

if ~exist('sofa_file','var') || isempty(sofa_file)
   sofa_file = fullfile(thispath,'..','HRIRs_sofa','HRIR_128_Meth5_IRC_53_Q10_symL_Itrp1_48000.sofa');
end
%% load SD HRIRs
H = hrtf_library_loader();
H.readSOFA(char(sofa_file));
ls_struct = get_ls_layout_config('Combined');
IR_SD = H.XYZ_to_IR_SD([deg2rad(ls_struct.azi); deg2rad(ls_struct.ele)]);

%% SD -> CLDFB via least squares error optimization
[~,num_ears,num_ch] = size(IR_SD);
num_cldfb_taps = 3;
IR_cldfb = zeros(60,num_cldfb_taps,num_ears,num_ch); % 60 frequency bands
eval_flag = 0; % optional, = 1 requires signal processing toolbox (fftfilt)
legacy_flag = 1; % = 1 used to indicate slightly too short buffers as used to generate tested coefficients 
for pos = 1:num_ch
   disp(['Channel ',num2str(pos),'/',num2str(num_ch)])
   for ear = 1:num_ears
      IR_cldfb(:,:,ear,pos) = fir_to_cldfb_fir( IR_SD(:,ear,pos), num_cldfb_taps, eval_flag, legacy_flag );
   end
end

%% CLDFB -> ROM
latency_s = 0.000666667;            % No added latency from conversion method
max_band = 50;                      % Compute 60 bands, but only use 50 in ROM table

IR_cldfb_rom = permute(IR_cldfb, [3 1 4 2]); % after permute: [ears(2), bands(60), chans(16), taps(3)]
IR_cldfb_rom = IR_cldfb_rom(:,1:max_band,:,:);

if ~exist('rom_c_file','var') || isempty(rom_c_file)
   rom_c_file = [thispath,'ivas_rom_binauralRenderer_combined.c']; % fullfile(thispath,'..','..','..','lib_rend',['ivas_rom_binauralRenderer_',order,'.c']);
end

fid = fopen(rom_c_file,'wt');

fprintf(fid, 'const float FASTCONV_HRIR_latency_s = %10.9ff;\n', latency_s);
write_one_ear( fid, 'const float leftHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]=', real(IR_cldfb_rom(1,:,:,:)));
write_one_ear( fid, 'const float leftHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]=', imag(IR_cldfb_rom(1,:,:,:)));
write_one_ear( fid, 'const float rightHRIRReal[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]=', real(IR_cldfb_rom(2,:,:,:)));
write_one_ear( fid, 'const float rightHRIRImag[BINAURAL_CONVBANDS][HRTF_LS_CHANNELS][BINAURAL_NTAPS]=', imag(IR_cldfb_rom(2,:,:,:)));

fclose(fid);

function write_one_ear( fid, first_line, IR_cldfb_rom)
IR_cldfb_rom = squeeze(IR_cldfb_rom);
[num_bands,num_chans, num_taps] = size(IR_cldfb_rom);
num_spaces = 4;
num_spaces_cur = 0;
fprintf(fid,[first_line,'\n{\n']);
num_spaces_cur = num_spaces_cur + num_spaces;
for band = 1:num_bands
   fprintf(fid,[blanks(num_spaces_cur),'{\n']);
   num_spaces_cur = num_spaces_cur + num_spaces;
   for chan = 1:num_chans
      fprintf(fid,[blanks(num_spaces_cur),'{']);
      for tap = 1:num_taps
         if tap == num_taps
            fprintf(fid,'%+ff',IR_cldfb_rom(band,chan,tap));
         else
            fprintf(fid,'%+ff, ',IR_cldfb_rom(band,chan,tap));
         end
      end
      if chan == num_chans
         fprintf(fid,'}\n');
      else
         fprintf(fid,'},\n');
      end
   end
   num_spaces_cur = num_spaces_cur - num_spaces;
   if band == num_bands
      fprintf(fid,[blanks(num_spaces_cur),'}\n']);
   else
      fprintf(fid,[blanks(num_spaces_cur),'},\n']);
   end
end
fprintf(fid,'};\n\n');
+6 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ function IR_cldfb = SHD_2_ROM( rom_c_file, sofa_file, ambi_order, hrir_len )
[thispath,~,~] = fileparts(mfilename('fullpath'));
thispath = [thispath,filesep];

%py_path = 'C:\Users\xxxx\AppData\Local\Programs\Python\Python39\python.exe'; % may look like this
if ~exist('sofa_file','var') || isempty(sofa_file)
   sofa_file = fullfile(thispath,'..','HRIRs_sofa','HRIR_128_Meth5_IRC_53_Q10_symL_Itrp1_48000.sofa');
end
@@ -49,6 +50,11 @@ if ~exist('hrir_len','var')
   hrir_len = 128;
end
%% convert sphere-sampled HRIRs to SHD HRIRs
% requires:
% python -m pip install sofar
% python -m pip install numpy

% convert sphere-sampled HRIRs to SHD HRIRs
[sofa_path,sofa_name, sofa_ext] = fileparts(sofa_file);
IR = generate_HOA_HRIRs_MOD_lens(ambi_order, sofa_path, [sofa_name,sofa_ext], hrir_len);

+0 −136
Original line number Diff line number Diff line
function ls_struct = get_ls_layout_config(ls_layout_config)

ls_struct = struct;
switch ls_layout_config
  case 'FOA'
    ls_struct.name = 'FOA';
    ls_struct.nb_channel = 4;
    ls_struct.azi = [0 0 0 0];
    ls_struct.ele = [0 0 0 0];
    ls_struct.isloudspeaker = 0;
    ls_struct.sba_order = 1;
    ls_struct.num_lfe = 0;
    ls_struct.lfe_index = zeros(0,0);
  case 'HOA2'
    ls_struct.name = 'HOA2';
    ls_struct.nb_channel = 9;
    ls_struct.azi = [0 0 0 0 0 0 0 0 0];
    ls_struct.ele = [0 0 0 0 0 0 0 0 0];
    ls_struct.isloudspeaker = 0;
    ls_struct.sba_order = 2;
    ls_struct.num_lfe = 0;
    ls_struct.lfe_index = zeros(0,0);
  case 'HOA3'
    ls_struct.name = 'HOA3';
    ls_struct.nb_channel = 16;
    ls_struct.azi = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
    ls_struct.ele = [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
    ls_struct.isloudspeaker = 0;
    ls_struct.sba_order = 3;
    ls_struct.num_lfe = 0;
    ls_struct.lfe_index = zeros(0,0);
  case {'CICP2', '2d0'}
    ls_struct.name = 'CICP2';
    ls_struct.nb_channel = 2;
    ls_struct.azi = [30 -30];
    ls_struct.ele = [0 0];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 0;
    ls_struct.lfe_index = zeros(0,0);
  case {'CICP6', 'cicp6', '5d1'}
    ls_struct.name = 'CICP6';
    ls_struct.nb_channel = 6;
    ls_struct.azi = [30 -30 0 0 110 -110];
    ls_struct.ele = [0 0 0 0 0 0];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 1;
    ls_struct.lfe_index = [4];
  case {'CICP12', 'cicp12', '7d1'} % 3 front, 4 surround + 1LFE
    ls_struct.name = 'CICP12';
    ls_struct.nb_channel = 8;
    ls_struct.azi = [30 -30 0 0 110 -110 135 -135];
    ls_struct.ele = [0 0 0 0 0 0 0 0];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 1;
    ls_struct.lfe_index = [4];    
  case {'CICP16', 'cicp16', '5d1p4'}
    ls_struct.name = 'CICP16';
    ls_struct.nb_channel = 10;
    ls_struct.azi = [30 -30 0 0 110 -110 30 -30 110 -110];
    ls_struct.ele = [0 0 0 0 0 0 35 35 35 35];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 1;
    ls_struct.lfe_index = [4];
  case {'CICP13', 'cicp13','22d2'}
    ls_struct.name = 'CICP13';
    ls_struct.nb_channel = 24;
    ls_struct.azi = [60 -60 0 0 135 -135 30 -30 180 0 90 -90 45 -45 0 0 135 -135 90 -90 180 0 45 -45];
    ls_struct.ele = [0 0 0 0 0 0 0 0 0 0 0 0 35 35 35 90 35 35 35 35 35 -15 -15 -15];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 2;
    ls_struct.lfe_index = [4 10];
  case {'CICP19', 'cicp19','7d1p4'}
    ls_struct.name = 'CICP19';
    ls_struct.nb_channel = 12;
    ls_struct.azi = [30 -30 0 0 135 -135 90 -90 30 -30 135 -135];
    ls_struct.ele = [0 0 0 0 0 0 0 0 35 35 35 35];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 1;
    ls_struct.lfe_index = [4];
  case {'Combined'}
    ls_struct.name = 'Combined';
    ls_struct.nb_channel = 15;
    ls_struct.azi = [30 -30 0 135 -135 110 -110 90 -90 30 -30 110 -110 135 -135];
    ls_struct.ele = [0 0 0 0 0 0 0 0 0 35 35 35 35 35 35];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 0;
  case {'Lebedev_26'}
    ls_struct.name = 'Leb26';
    ls_struct.nb_channel = 26;
    ls_struct.azi = [0 180.0 90.0 270.0  0     0   90.0  90.0  270.0  270.0  0     0   180.0  180.0  45.0  315.0  135.0  225.0 45.0  45.0   315.0  315.0  135.0  135.0  225.0 225.0];
    ls_struct.ele = [0   0    0     0   90.0 -90.0 45.0 -45.0   45.0  -45.0 45.0 -45.0  45.0  -45.0   0      0      0      0   35.3 -35.3    35.3  -35.3   35.3  -35.3   35.3 -35.3];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 0;
  case {'cube_8'}
    ls_struct.name = 'Cub8';
    ls_struct.nb_channel = 8;
    ls_struct.azi = [45 45 135 135 225 225 315 315];
    ls_struct.ele = [35.3 -35.3 35.3 -35.3 35.3 -35.3 35.3 -35.3];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 0;
  case {'BINAURAL', 'BINAURAL_ROOM'}
    ls_struct.name = 'BINAURAL';
    ls_struct.nb_channel = 2;
    ls_struct.azi = [90 -90];
    ls_struct.ele = [0 0];
    ls_struct.isloudspeaker = 2;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 0;
  case {'STEREO'}
    ls_struct.name = 'STEREO';
    ls_struct.nb_channel = 2;
    ls_struct.azi = [90 -90];
    ls_struct.ele = [0 0];
    ls_struct.isloudspeaker = 2;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 0;
  case {'MONO'}
    ls_struct.name = 'MONO';
    ls_struct.nb_channel = 1;
    ls_struct.azi = [0];
    ls_struct.ele = [0];
    ls_struct.isloudspeaker = 1;
    ls_struct.sba_order = -1;
    ls_struct.num_lfe = 0;
  otherwise
    error('Loudspeaker layout not supported!');
end
+3 −44
Original line number Diff line number Diff line
@@ -157,11 +157,6 @@ classdef hrtf_library_loader < handle
            obj.process_lib(H, Data.SamplingRate);
        end
        
        function IR = XYZ_to_IR_SD( this, XYZ )
            [HRTF_L, HRTF_R] = this.getHRTF_SD(XYZ);
            IR = permute(cat(3,HRTF_L,HRTF_R),[1,3,2]);
        end
        
        function IR = XYZ_to_IR( this, XYZ )
            IR = permute(cat(3,this.getHRTF_L(XYZ),this.getHRTF_R(XYZ)),[1,3,2]);
        end
@@ -229,19 +224,6 @@ classdef hrtf_library_loader < handle
            obj.Last_UV=[];
        end
        
        function [HRTFs_L, HRTFs_R] = getHRTF_SD(obj, varargin)
            % GETHRTF_SD Get the SD HRTFs for both ears from the library
            % Given [N] direction-of-arrival vectors, returns an array
            % of size [Len]x[N], containing the N HRTFs.
            % Examples:
            %  HRTFs = H.getHRTF_SD(Az,El)    % Az and El are both Nx1 or 1xN vectors (in radians)
            %  HRTFs = H.getHRTF_SD( Angles ) % Angles is a 2xN array of Az,El column pairs (in radians)
            %  HRTFs = H.getHRTF_SD(X, Y, Z)  % X,Y,Z are all 1xN or Nx1 vectors
            %  HRTFs = H.getHRTF_SD(Vects)    % Vects is a 3xN array of X,Y,Z column vectors
            UnitVecs = make_unit_vectors(varargin{:});
            [HRTFs_L, HRTFs_R] = obj.Fetch_Discrete_HRTFs(UnitVecs);
        end
 
        function HRTFs = getHRTF_L(obj,varargin)
            % GETHRTF_L Get one or more Left-ear HRTFs from the library
            % Given [N] direction-of-arrival vectors, returns an array
@@ -361,32 +343,9 @@ classdef hrtf_library_loader < handle
            end
        end

        function [TempL,TempR]=Fetch_Discrete_HRTFs(obj, UnitVecs)
            % We have set of unit-vectors, so we need to fetch the Left/Right
            % HRTFs at these (interpolated) angle positions
            NoVecs=size(UnitVecs,2);
            TempL=zeros(size(obj.Discrete_HRTFs,1),NoVecs);
            TempR=zeros(size(obj.Discrete_HRTFs,1),NoVecs);
            for k=1:NoVecs
                % For each direction (specified by a column of UnitVecs), we need
                % to figure out which HRTF Direction Vectors match the
                % given position
                IndSubset=1:size(obj.Discrete_UnitVectors,2);
                Dists=sum( (obj.Discrete_UnitVectors - repmat(UnitVecs(:,k),[1 size(obj.Discrete_UnitVectors,2)])).^2);
                [minDist, Dir] = min(Dists(IndSubset));
                % 10e-e4 is roughly the error for 1deg offset on the sphere 
                if abs(minDist) > 10e-3
                    error("Could not find an IR exactly matching this position, please check HRTF set!");
                end
                
                TempL(:,k)=obj.Discrete_HRTFs(:,Dir,1);
                TempR(:,k)=obj.Discrete_HRTFs(:,Dir,2);
            end
        end
    
        function [TempL,TempR]=Interpolate_Discrete_HRTFs(obj,UnitVecs)
        
            % We have set of unit-vectors, so we need to build the Left/Right
            % We have set of unit-vectors, so we need to buld the Left/Right
            % HRTFs at these (interpolated) angle positions
            NoVecs=size(UnitVecs,2);
            TempL=zeros(size(obj.Discrete_HRTFs_GD_Mag,1),NoVecs);
@@ -403,7 +362,7 @@ classdef hrtf_library_loader < handle
                    % Find the HRTF_Library direction closest to our target direction
                    [~,NextDir] = min(Dists(IndSubset));
                    v=obj.Discrete_UnitVectors(:,IndSubset(NextDir));
                    GotSet=[GotSet IndSubset(NextDir)]; % Add this direction to the set
                    GotSet=[GotSet IndSubset(NextDir)]; % Add this directon to the set
                    IndSubset=IndSubset([1:NextDir-1,NextDir+1:end]);
                    tmpV=UnitVecs(:,k)-v;
                    if sum(tmpV.^2)>1e-20