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

clear all
close all
clc

addpath( './lib' )
a_configureFileNamesAndDirectories


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


%% LOAD DATA FROM FILES
disp( [ 'NOISE - Loading multi-channels files: ' recordedFileName ] );
[ fileToProcess, fs ]       = audioread( recordedNoiseFile );
outputWavFileName           = encodedNoiseWavFileName;
outputMatFileName           = encodedNoiseMatFileName;
if ~isdir( encodedNoiseFolder )
    mkdir( encodedNoiseFolder )
end

if strcmp( encodingFilterMatrixFileName( end-3 : end ), '.mat' ) % check file extension
    
    load( encodingFilterMatrixFile );
    virtualMicNumber            = size( Matrix, 1 );
    arraySize                   = size( Matrix, 2 );
    fprintf( [ 'Loaded matrix for ' num2str( virtualMicNumber ) ' directions.\n'] );

    % Codifica con matrice di coefficienti anzichè matrice di filtri FIR
    encodedFormat               = fileToProcess * Matrix';
    fprintf( 'Matrix multiplication done \n' );
    
else
    
    % filter matrix for beamforming
    [ encodingFilter, fs ]      = audioread ( encodingFilterMatrixFile );
    virtualMicNumber            = size ( encodingFilter, 2 );
    arraySize                   = size( fileToProcess, 2 );

    fprintf( [ 'Loaded matrix for ' num2str( virtualMicNumber ) ' directions.\n'] );
    % encoding matrix is [ mic-IN x vmic-OUT x Nsamples]
    [ encodingMatrix, ~ ]       = load_ir( encodingFilterMatrixFile, arraySize, virtualMicNumber ); 
    
    %% SPS transform
    limitLength                 = 200000;
    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 );% convolving with SPS matrix
    end
    encodedFormat               = squeeze( encodedFormat )';                    % eliminate exceeding matrix dimension
    
    figure
    subplot( 3, 1, 1 )
    plot( fileToProcess( :, 1 ) )
    xlim( [ 0 size( fileToProcess, 1 ) ] )
    xlabel( 'Samples' )
    grid on
    title( 'Original audio - first mic' )
    subplot( 3, 1, 2 )
    plot( encodedFormat( :, 1 ) )
    xlim( [ 0 size( encodedFormat, 1 ) ] )
    xlabel( 'Samples' )
    grid on
    title( 'Encoded audio - first mic' )

    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 ), : );

    subplot( 3, 1, 3 )
    plot( encodedFormat( :, 1 ) )
    xlim( [ 0 size( encodedFormat, 1 ) ] )
    xlabel( 'Samples' )
    grid on
    title( 'Encoded audio - removed delay' )

end    

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


%% Normalize and save multich .wav file
if saveWavEnable
    maxAbsValue                 = max( max( abs( encodedFormat ) ) );       % searc 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' );
