%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% (c) Copyright 2014 Hexoskin
% Permission to use, copy, modify, and distribute this software for any 
% purpose with or without fee is hereby granted, provided that the above 
% copyright notice and this permission notice appear in all copies. The 
% software is provided 'as is' and the author disclaims all warranties with
% regard to this software including all implied warranties of
% merchantability and fitness. In no event shall the author be liable for
% any special, direct, indirect, or consequential damages or any damages
% whatsoever resulting from loss of use, data or profits, whether in an 
% action of contract, negligence or other tortious action, arising out of
% or in connection with the use or performance of this software.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%version = '1.0.2';


function data = load_hx_data(path, filename)
% data = loadData(path, filename) converts a particular file from wav or
% csv to an array variable
%
%   data: is the output array size = [x, 2]
%   path: is the file to the path
%   filename: is the name of the file


if strcmpi(filename(end-2:end), 'wav')
    data = loadWave(path, filename);
elseif  strcmpi(filename(end-2:end), 'csv')
    data = loadCsv(path, filename);
else
    data = [];
    disp('invalid file extension, must be .wav or .csv')
end



function data = loadWave(path, filename)
% data = loadWave(path, filename) load a wav (synchronous) file. The value
% are returned for each second. The time t=0 correspond to the beginning of
% the record.
%
%   data: is the array output of the decoded data
%   path: is the file to the path
%   filename: is the name of the file

filename2 = fullfile(path, filename);
if exist('OCTAVE_VERSION', 'builtin')
    [y, Fs, nbits, opts] = audioread(filename2);
else
    try
        [y, Fs] = audioread(filename2, 'native');
    catch
        data = [];
        return
    end
    
end
y = double(y);
data = getScale(filename, y, path);


function data = loadCsv(path, filename)
% data = loadCsv(path, filename) load an csv (asynchronous) file. The
% value are returned in second. The time t=0 correspond to the beginning of
% the record.
%
%   data: is the array output of the decoded data
%   path: is the file to the path
%   filename: is the name of the file

filename2 = fullfile(path, filename);
data = csvread(filename2,1);
data = getScale(filename, data, path);


function [freq_device, freq_signal] = getDeviceFreq(filename, path)
freq_signal = 1;
freq_device = 256;
try
    freq_signal = audioinfo(fullfile(path, filename));
catch
end
filenames = {'ECG_I.wav', 'respiration_thoracic.wav', 'acceleration_X'};
for i =1:3
     try
         aa = audioinfo(fullfile(path, filenames{i}));
         if any(ismember([125, 250, 50], aa.SampleRate))
             freq_device = 1000;
             break
         end
     catch
     end 
end


function y = getScale(filename, y, varargin)
% perform data staling and add time
if nargin == 3
    [freq_device, freq_signal] = getDeviceFreq(filename, varargin{1}); 
else
    freq_device = 256;
    freq_signal = 1;
end
filename2 = filename(1:end-4);
if freq_device == 256
    GAIN_ECG = 0.0064 ; 
    OFFSET_ECG = -1360 * 0.0064 ;
    dt_e = 1/256 ;
    dt_r = 1/128 ;
    dt_a = 1/64;
    dt_o = 1/64 ;
    br_gain = 1 ;
    gain_resp = 13.28;
    tmp_gain = 1;
else
    GAIN_ECG =  0.001;
    OFFSET_ECG =   0;
    dt_e =  1/250;
    dt_r =  1/125;
    dt_a =  1/50;
    dt_o =  1/75;
    br_gain =  .1;
    gain_resp =  1;
    tmp_gain = 1/256;
end
True = 1;
False = 0;

% filename_in, csv_name, quality_signal_name, unit, dt,dt_offset, gain, offset, signed, round, datatype, is_wav
specs = { 'ECG_I', 'ECG_I', '', 'mV', dt_e, 0, GAIN_ECG, OFFSET_ECG, 1, 5, 4113, True;
        'ECG_II', 'ECG_II', '', 'mV', dt_e, 0, GAIN_ECG, OFFSET_ECG, 1, 5, 4114, True;
        'ECG_III', 'ECG_III', '', 'mV', dt_e, 0, GAIN_ECG, OFFSET_ECG, 1, 5, 4115, True;
        'ECG_quality', 'ECG_quality', 'NONE', 'na', 1, 1, 1, 0, 0, 0, 1006, True;
        'respiration_thoracic', 'respiration_thoracic', '', 'na', dt_r, 0, 1, 0, 0, 5, 4129, True;
        'respiration_abdominal', 'respiration_abdominal', '', 'na', dt_r, 0, 1, 0, 0, 5, 4130, True;
        'acceleration_X', 'acceleration_X', '', 'G', dt_a, 0, 1 / 256, 0, 1, 8, 4145, True;
        'acceleration_Y', 'acceleration_Y', '', 'G', dt_a, 0, 1 / 256, 0, 1, 8, 4146, True;
        'acceleration_Z', 'acceleration_Z', '', 'G', dt_a, 0, 1 / 256, 0, 1, 8, 4147, True;
        'ppgdo', 'ppgdo', '', 'na', dt_a, 0, 1, 0, 0, 5, 64, True;
        'ppgDisc', 'ppgDisc', '', 'na', dt_a, 0, 1, 0, 0, 0, 64, True;
        'ppgOOT', 'ppgOOT', '', 'na', dt_a, 0, 1, 0, 0, 5, 64, True;
        'heart_rate', 'heart_rate', 'heart_rate_quality', 'bpm', 1, 1, 1, 0, 0, 0, 19, True;
        'energy_mifflin_keytel', 'energy_mifflin_keytel', '', 'watt', 1, 1, 1, 0, 0, 0, 42, True;
        'heart_rate_quality', 'heart_rate_quality', 'NONE', 'na', 1, 1, 1, 0, 0, 0, 1000, True;
        'breathing_rate', 'breathing_rate', 'breathing_rate_quality', 'rpm', 1, 1, br_gain, 0, 0, 0, 33, True;
        'breathing_rate_quality', 'breathing_rate_quality', 'NONE', 'na', 1, 1, 1, 0, 0, 0, 1001, True;
        'minute_ventilation', 'minute_ventilation_raw', '', 'ml/min', 1, 1, gain_resp, 0, 0, 5, 36, True;
        'tidal_volume', 'tidal_volume_raw', '', 'ml', 1, 1, gain_resp, 0, 0, 5, 37, True;
        'minute_ventilation_adjusted', 'minute_ventilation_adjusted', '', 'ml/min', 1, 1, 10, 0, 0, 5, 38, True;
        'tidal_volume_adjusted', 'tidal_volume_adjusted', '', 'ml', 1, 1, 1, 0, 0, 5, 39, True;
        'minute_ventilation_cl', 'minute_ventilation_adjusted', '', 'ml/min', 1, 1, 10, 0, 0, 5, 38, True;
        'tidal_volume_ml', 'tidal_volume_adjusted', '', 'ml', 1, 1, 1, 0, 0, 5, 39, True;
        'actigraphy', 'actigraphy', '', 'G', 1, 1, 1 / 256, 0, 1, 8, 54, True;
        'activity', 'activity', '', 'G', 1, 1, 1 / 256, 0, 1, 8, 49, True;
        'cadence', 'cadence', '', 'spm', 1, 1, 1, 0, 0, 0, 53, True;
        'temperature_celcius', 'temperature_celcius', '', 'Celcius', 1, 1, tmp_gain, 0, 1, 8, 81, True;
        'temperature', 'temperature', '', 'Celcius', 1, 1, tmp_gain, 0, 1, 8, 81, True;
        'RESP_TMPR', 'RESP_TMPR', '', 'Celcius', 1, 1, 0.01, 0, 1, 8, 338, True;
        'systolic_pressure', 'systolic_pressure', '', 'mmHg', 1, 1, 1, 0, 0, 5, 98, True;
        'systolic_pressure_adjusted', 'systolic_pressure_adjusted', '', 'mmHg', 1, 1, 1, 0, 0, 5, 99, True;
        'SPO2', 'SPO2', 'SPO2_quality', 'Percent', 1, 1, 1, 0, 0, 0, 66, True;
        'SPO2_quality', 'SPO2_quality', 'NONE', 'na', 1, 1, 1, 0, 0, 0, 1002, True;
        'BATT_ST_CHANNEL_CHAR', 'BATT_ST_CHANNEL_CHAR', '', 'na', 1, 1, 1, 0, 0, 0, 247, True;
        'TEMP_ST_CHANNEL_CHAR', 'TEMP_ST_CHANNEL_CHAR', '', 'na', 1, 1, 1, 0, 0, 0, 246, True;
        'HRV_HF', 'HRV_HF', '', 'ms^2', 300, 300, 1 / 10, 0, 0, 8, 277, True;
        'HRV_LF_normalized', 'HRV_LF_normalized', '', '', 300, 300, 1 / 100, 0, 0, 8, 273, True;
        'HRV_LF', 'HRV_LF', '', 'ms^2', 300., 300, 1 / 10, 0, 0, 8, 276, True;
        'NN_over_RR', 'NN_over_RR', '', '%', 300, 300, 1 / 100, 0, 0, 8, 274, True;
        'ANN', 'ANN', '', 's', 300, 300, 1 / freq_device / 16, 0, 0, 8, 271, True;
        'SDNN', 'SDNN', '', 's', 300, 300, 1 / freq_device / 16, 0, 0, 8, 272, True;
        'HRV_triangular', 'HRV_triangular', '', 'na', 300, 300, 1 / 100, 0, 0, 5, 275, True;
        'PPG', 'PPG', '', 'na', dt_o, 0, 1, 0, 0, 5, 64, True;
        'QRS', 'QRS_epoch', '', 'na', 1, 0, 1, 0, 0, 0, 17, False;  
        'RR_interval', 'RR_interval_epoch', 'RR_interval_quality', 's', 1, 0, 1 / freq_device, 0, 0, 8, 18, False;
        'inspiration', 'inspiration_epoch', '', 'na', 1, 0, 1, 0, 0, 0, 34, False;  
        'expiration', 'expiration_epoch', '', '', 1, 0, 1, 0, 0, 0, 35, False;  
        'step', 'step_epoch', '', 'step', 1, 0, 1, 0, 0, 0, 52, False;  
        'PTT', 'PTT_epoch', '', 's', 1, 0, 1 / freq_device, 0, 0, 0, 97, False;
        'device_position', 'device_position_epoch', '', 'na', 1, 0, 1, 0, 0, 0, 269, False;  
        'sleep_position', 'sleep_position_epoch', '', 'na', 1, 0, 1, 0, 0, 0, 270, False;  
        'sleep_phase', 'sleep_phase_epoch', '', 'na', 1, 0, 1, 0, 0, 0, 280, False;  
        'NN_interval', 'NN_interval_epoch', '', 's', 1, 0, 1 / freq_device, 0, 0, 8, 318, False;  
        'RR_interval_realigned', 'RR_interval_realigned_epoch', '', 's', 1, 0, 1 / freq_device, 0, 0, 8, 319, False;
        'RR_interval_quality', 'RR_interval_quality_epoch', '', 'na', 1, 0, 1 / freq_device, 0, 0, 0, 1004, False};
    
idx = find(strcmpi(specs(:,1), filename2));
if idx 
    dt = specs{idx, 5};
    dt_offset = specs{idx, 6};
    gain = specs{idx, 7};
    offset = specs{idx, 8};
    signed = specs{idx, 9};
else
    dd=43;
end

if isempty(y) 
    data = [];
elseif size(y, 2) == 1
    if ~signed
        y(y < 0) = y(y < 0) + 2^16; 
    end
    if offset 
        y = y * gain + offset;
    else
        y = y * gain;
    end
    t = (0: (length(y)-1)) * dt + dt_offset;
    data = [t', y];
else
    % csv file
    data = y;
    if all(round(y(:, 2)) == y(:, 2)) 
        % convert only if integer value, otherwise, it was already
        % converted
        data(:, 1) = data(:, 1)*gain;
    end
end


