%% GRANULES - This function interprets the parameters outlined in InputParameters_Functioncall.m then calls the grain.m function Gn times.
function [Y,grains] = granules (x,fs,Gn,Lout,GDmax,GDmin,channelsIN,Read_Type,W,ENV)

Lin=length(x);% Length of input signal

% if statement providing the user with the option to enter Lout in seconds
% or make it the length of the input signal
if Lout == length(x);
    Lout = length(x);
else
Lout = round(fs*Lout);%convert seconds to samples
end

Y=zeros (1,Lout);%Pad output with zeros ready for processing

GDmax = round(fs*(GDmax/1000));%convert milliseconds to samples

GDmin = round(fs*(GDmin/1000));%convert milliseconds to samples

GD = round((GDmax-GDmin)*rand(1,Gn))+GDmin;%calculate GD based on GDmin and GDmax

if channelsIN == 1;%force signal stereo if input is mono
    x = [x, -x];
end

% if statement defining read types
if Read_Type == 1;
    initIN = ceil(linspace(1,Lin-GDmax,Gn));%linear progression
elseif Read_Type == 2;
    initIN = sort(ceil(linspace(1,Lin-GDmax,Gn)),'descend');%backwards progression
elseif Read_Type == 3;
    initIN = ceil ((Lin - GDmax)*rand(1,Gn));%random progression
end


initOUT = ceil(linspace(1,Lout - GDmax,Gn));%initOUT linear always (see documentation)

endOUT=initOUT+GD-1;%define endOUT for use in synthesis loop

%if statement defining ENV types
if ENV == 1;
   ENV = rand(1,Gn);%random amplitude coefficient
elseif ENV == 2;
   ENV = gausswin(Gn);%gaussian envelope across output
elseif ENV == 3;
   ENV = sort(rand(1,Gn));%crescendo through output
elseif ENV == 4;
    ENV = sort(rand(Gn,1),'descend');%diminuendo through output
end
    
% The synthesis loop - calls the grain function Gn times. The second line
% arranges the grains in the output and applies ENV.
for k=1:Gn
    
    grains = grain(x,initIN(k),GD(k),W);
    
    Y(initOUT(k):endOUT(k))=Y(initOUT(k):endOUT(k))+ENV(k)*grains;
end

    Y = Y';% convert to column vector
    Y = Y./max(abs((Y)));%normalise output to avoid distortion.
    Y = Y.*0.9;          

end
