classdef vowel
    % VOWEL: this is a vowel represented by its F1 and F2,
    % both F1 and F2 are sampled from a gaussian distribution
    % with the means which are given when constructing this vowel
    
    properties (Constant)
        % All the properties are just copied from praat
        ambient_stdev_erb = 1.0
        auditory_spreading_erb = 0.68
        n_auditory_nodes = 49
        fmin_erb = 4.0
        fmax_erb = 28.0
        dist_between_labels_erbs = 3.0 % this is a parameter for visualisation
        erbs_per_node = (vowel.fmax_erb - vowel.fmin_erb) / (vowel.n_auditory_nodes - 1)
        auditory_spreading_nodes = vowel.auditory_spreading_erb / vowel.erbs_per_node
    end
    
    methods (Static)

        function [f1_sample, f2_sample] = sample(f1_erb, f2_erb)
            if ~f1_erb || ~f2_erb
                error("runtime error: trying to sample vowel with either F1 or F2 not specified")
            end
            f1_sample = normrnd(f1_erb, vowel.ambient_stdev_erb);
            f2_sample = normrnd(f2_erb, vowel.ambient_stdev_erb);
        end

        function [f1_sample, f2_sample] = sample_with_std(f1_erb, f2_erb, f1_std, f2_std)
            if ~f1_erb || ~f2_erb
                error("runtime error: trying to sample vowel with either F1 or F2 not specified")
            end
            f1_sample = normrnd(f1_erb, f1_std);
            f2_sample = normrnd(f2_erb, f2_std);
        end

        function input_vector = create_zero_input_vector()
            input_vector = zeros(1, vowel.n_auditory_nodes);
        end
        
        function input_vector = create_input_vector(f1_erb, f2_erb)
            input_vector = zeros(1, vowel.n_auditory_nodes);
            
            % in case vowel is not present
            if f1_erb < 4 || f1_erb > 28 || f2_erb < 4 || f2_erb > 28
                input_vector = input_vector - 2.0;
                return
            end
            
            % in case vowel is present
            auditory_node_f1 = 1 + (f1_erb - vowel.fmin_erb) / vowel.erbs_per_node;
            auditory_node_f2 = 1 + (f2_erb - vowel.fmin_erb) / vowel.erbs_per_node;
            for i = 1:vowel.n_auditory_nodes
                input_vector(i) = input_vector(i) ...
                    + 5 * exp(-0.5 * ((i - auditory_node_f1) / vowel.auditory_spreading_nodes) ^ 2) ...
                    + 5 * exp(-0.5 * ((i - auditory_node_f2) / vowel.auditory_spreading_nodes) ^ 2) - 1.0;   
            end
        end
    end
end

