function [plotMask, plotAudio, plotFlag] = profileKeywordSpotting(x)  
% profileKeywordSpotting receives speech input and returns the input data
% with the predicted speech mask.
%#codegen

% Copyright 2020-2021 The MathWorks, Inc.

% Declare persistent variables
persistent dataBuff plotBuff featureBuff KWSNet M S ;

% Set audio parameters
fs = 16000;
windowLength = 512;
overlapLength = 384;
hopLength = windowLength - overlapLength;
numHopsPerUpdate = 16;
numFeatures = 39;

% Load the pre-trained network and initialize persistent buffers
if isempty(KWSNet)
    KWSNet = coder.loadDeepLearningNetwork('./KeywordSpotting/KWSNet.mat');
    structM = coder.load('./KeywordSpotting/KWSNet.mat',"M","S");
    tempM = structM.M;
    tempS = structM.S;
    M = repmat(tempM,numHopsPerUpdate,1);
    S = repmat(tempS,numHopsPerUpdate,1);
    dataBuff = dsp.AsyncBuffer(windowLength);
    featureBuff = dsp.AsyncBuffer(numHopsPerUpdate);
    plotBuff = dsp.AsyncBuffer(numHopsPerUpdate*windowLength);
end

% Write input data to FIFO buffers
write(dataBuff,x);
write(plotBuff,x);

% Read data frame
frame = read(dataBuff,windowLength,overlapLength);

% Compute MFCCs and write it to feature buffer
features = generateKeywordFeatures(frame,fs);
featuresT = features.';
featuresT = featuresT(1:numFeatures);
write(featureBuff,featuresT);

if featureBuff.NumUnreadSamples == numHopsPerUpdate        
    featureMatrix = read(featureBuff);
    featureMatrix(~isfinite(featureMatrix)) = 0;
    featureMatrix = (featureMatrix - M)./S;
    
    % Predict output probabilities using predict 
    predictedScores = predict(KWSNet, featureMatrix.');
    [~, predictedMaskFrameIndex] = max(predictedScores);
    
    predictedMaskFrameIndex = single(predictedMaskFrameIndex) - 1;
    replicatedMaskFrames = single(repmat(predictedMaskFrameIndex, hopLength, 1));
    replicatedMaskSamples = replicatedMaskFrames(:);
    
    predictedLabel = mode(replicatedMaskSamples);    
    plotMask = repmat(predictedLabel, numHopsPerUpdate * hopLength,1);
   
    plotAudio = single(read(plotBuff));   
    plotFlag = true;
else
    plotMask = single([]);
    plotAudio = single(0);
    plotFlag = false;
end

end
