%% Count Label Values and Create Datastores
% Specify the path to a set of audio signals included as MAT-files with MATLAB®. Each file contains a signal variable and a sample rate. List the names of the files.

folder = fullfile(matlabroot,"toolbox","matlab","audiovideo");
lst = dir(append(folder,"/*.mat"));
nms = {lst(:).name}'

% Create a signal datastore that points to the specified folder. Set the sample rate variable name to Fs, which is common to all files. Generate a subset of the datastore that excludes the file mtlb.mat. Use the subset datastore as the source for a labeledSignalSet object.

sds = signalDatastore(folder,"SampleRateVariableName","Fs");
sds = subset(sds,~strcmp(nms,"mtlb.mat"));
lss = labeledSignalSet(sds);

%
% Create three label definitions to label the signals:
% Define a logical attribute label that is true for signals that contain human voices.
% Define a numeric point label that marks the location and amplitude of the maximum of each signal.
% Define a categorical region-of-interest (ROI) label to pick out nonoverlapping, uniform-length random regions of each signal.
% Add the signal label definitions to the labeled signal set.

vc = signalLabelDefinition("Voice",'LabelType','attribute', ...
    'LabelDataType','logical','DefaultValue',false);
mx = signalLabelDefinition("Maximum",'LabelType','point', ...
    'LabelDataType','numeric');
rs = signalLabelDefinition("RanROI",'LabelType','ROI', ...
    'LabelDataType','categorical','Categories',["ROI" "other"]);
addLabelDefinitions(lss,[vc mx rs])

%
% Label the signals:
% Label 'handel.mat' and 'laughter.mat' as having human voices.
% Use the islocalmax function to find the maximum of each signal. Label its location and value.
% Use the randROI function to generate as many regions of length N/10 samples as can fit in a signal of length N given a minimum separation of N/6 samples between regions. Label their locations and assign them to the ROI category.
% When labeling points and regions, convert sample values to time values. Subtract 1 to account for MATLAB® array indexing and divide by the sample rate.

kj = 1;
while hasdata(sds)
    
    [sig,info] = read(sds);
    fs = info.SampleRate;

    [~,fn] = fileparts(info.FileName);
    if fn=="handel" || fn=="laughter"
        setLabelValue(lss,kj,"Voice",true)
    end
    
    xm = find(islocalmax(sig,'MaxNumExtrema',1));
    setLabelValue(lss,kj,"Maximum",(xm-1)/fs,sig(xm))

    N = length(sig);
    rois = randROI(N,round(N/10),round(N/6));
    setLabelValue(lss,kj,"RanROI",(rois-1)/fs,repelem("ROI",size(rois,1)))

    kj = kj+1;
    
end

%
% Verify that only two signals contain voices.

countLabelValues(lss,"Voice")

% Verify that two signals have a maximum amplitude of 1.

countLabelValues(lss,"Maximum")

% Verify that each signal has four nonoverlapping random regions of interest.

countLabelValues(lss,"RanROI")

%
% Create two datastores with the data in the labeled signal set:
% The signalDatastore object sd contains the signal data.
% The arrayDatastore object ld contains the labeling information. Specify that you want to include the information corresponding to all the labels you created.

[sd,ld] = createDatastores(lss,["Voice" "RanROI" "Maximum"]);

% Use the information in the datastores to plot the signals and display their labels.
% Use a signalMask object to highlight the regions of interest in blue.
% Plot yellow lines to mark the locations of the maxima.
% Add a red axis label to the signals that contain human voices.

tiledlayout flow

while hasdata(sd)

    [sg,nf] = read(sd);
    
    lbls = read(ld);
    
    nexttile
    
    msk = signalMask(lbls{:}.RanROI{:},'SampleRate',nf.SampleRate);    
    plotsigroi(msk,sg)
    colorbar off
    xlabel('')
    
    xline(lbls{:}.Maximum{:}.Location, ...
        'LineWidth',2,'Color','#EDB120')
    
    if lbls{:}.Voice{:}
        ylabel('VOICED','Color','#D95319')
    end

end

%

function roilims = randROI(N,wid,sep)

num = floor((N+sep)/(wid+sep));
hq = histcounts(randi(num+1,1,N-num*wid-(num-1)*sep),(1:num+2)-1/2);
roilims = (1 + (0:num-1)*(wid+sep) + cumsum(hq(1:num)))' + [0 wid-1];

end

% Copyright 2020 The MathWorks, Inc.