% GenerateEncodedFormat.m Generation of encoded spatial format from array recordings.
% This script takes multichannels IRs recording as input, convolves it with SPS matrix and stores the 
% results in a .mat or .wav file.
%
% INPUT
% - IRs from microphone array
% - SPS matrix filter or Ambisonics matrix filter (.mat / .wav)
%
% OUTPUT
% - IRs in SPS format (.mat / .wav)
%
% Authors: Daniel Pinardi, Marco Binelli.
% University of Parma, 2017
% Last review: 05/2023, Daniel Pinardi

clear variables
close all
clc

addpath( './lib' )
a_configureFileNamesAndDirectories


%% SAVE ALSO WAV FILE: POSSIBLE VALUES '0 -> disable' , '1 -> enable'
saveWavEnable				= 1;


%% LOAD DATA FROM FILES
if exist( irsMatFileName, 'file' ) ~= 0
	% IRs .mat file
	disp( [ 'IRS - Loading multi-channels files: ' irsMatFileName ] );
	load( irsMatFileName );
	fileToProcess           = irs;                                          % rename imported file
	clear irs
else
	disp( [ 'NOISE - Loading multi-channels files: ' recordedSweepFile ] );
	[ fileToProcess, ~ ]	= audioread( recordedSweepFile );
end

outputWavFileName			= encodedIrsWavFileName;
outputMatFileName			= encodedIrsMatFileName;
if ~isfolder( encodedIrsFolder )
	mkdir( encodedIrsFolder )
end

% filter matrix for beamforming
[ encodingFilter, fs ]      = audioread( encodingFilterMatrixFile );
virtualMicNumber            = size( encodingFilter, 2 );
arraySize                   = size( fileToProcess, 2 );
filtersLength               = size( encodingFilter, 1 ) ./ arraySize;

fprintf( [ '\nNumber of input channels: ' num2str( arraySize ) '\n' ] );
fprintf( [ 'Number of output channels: ' num2str( virtualMicNumber ) '\n' ] );
fprintf( [ 'Number of samples of each filter: ' num2str( filtersLength ) '\n\n' ] )

% encoding matrix is [ mic-IN x vmic-OUT x Nsamples ]
[ encodingMatrix, ~ ]       = load_ir( encodingFilterMatrixFile, arraySize, virtualMicNumber ); 
    
    
%% PROCESSING
limitLength                 = 200000; % depending on RAM of computer, might be necessary to decrease
fileToProcessLength         = length( fileToProcess );

if  fileToProcessLength    <= limitLength
    % Reshaping matrix to use convolve library function: matrix_conv
    fileToProcessMatrix     = reshape( fileToProcess', 1, arraySize, fileToProcessLength );   
    encodedFormat           = matrix_conv( fileToProcessMatrix, encodingMatrix );   % convolving with SPS matrix
else
    % Reshaping matrix to use convolve library function: oa_multichannel_conv
    fileToProcessMatrix     = reshape( fileToProcess', arraySize, fileToProcessLength, 1 );   
    encodedFormat           = oa_multichannel_conv( fileToProcessMatrix, encodingMatrix, precision );% convolving with SPS matrix
end
encodedFormat               = squeeze( encodedFormat )';                    % eliminate exceeding matrix dimension

delay						= zeros( arraySize, virtualMicNumber );
for in = 1 : arraySize
    for out = 1 : virtualMicNumber
        [ ~, delayInOut ]   = max( abs( encodingMatrix( in, out, : ) ) );
        delay( in, out )    = delayInOut;
    end
end
delay                       = round( mean( delay, 'all' ) );
encodedFormat               = encodedFormat( delay+1 : delay + length( fileToProcess ), : );
    

%% Exporting results in a .mat file
fprintf( '\n' )
disp( [ 'Saving ' num2str( virtualMicNumber ) ' channels in MAT files: ' outputMatFileName ] );
save( outputMatFileName, 'encodedFormat', 'fs', '-v7.3', '-nocompression' );


%% Normalize and save multich .wav file
if saveWavEnable == 1
    maxAbsValue                 = max( max( abs( encodedFormat ) ) );       % search for absolute max value
    encodedFormat               = encodedFormat ./ maxAbsValue;             % normalize IRs between -1 and +1
    disp( [ 'Saving ' num2str( virtualMicNumber ) ' channels in WAV files: ' outputWavFileName ] );
    audiowrite( outputWavFileName, encodedFormat, fs, 'BitsPerSample', 32 );
end

rmpath( './lib' )
fprintf( '\nEnded correctly.\n\n' );
