function HelperSpeechCommandRecognitionRasPi(hostIPAddress) %#codegen
% C++ EXECUTABLE generated using MATLAB Coder for this function, runs on
% Raspberry Pi board. It receives speech data from the matlab script
% running on host PC/LAPTOP through UDP and process it to get the
% predicted scores and audio features. This function sends the predicted
% scores and auditory feature matrix to the UDP port of the host PC/LAPTOP.
% Matlab script running on host PC/LAPTOP receives this data and shows
% the results on Time scope and Matrix Viewer

% Copyright 2020 The MathWorks, Inc.

% Load Network
trainedNet = coder.loadDeepLearningNetwork('commandNet.mat');

% Setting Real-Time Parameters
fs = 16000;
classificationRate = 20;
NumLabels = 12;
countThreshold = ceil(classificationRate*0.2);
probThreshold = 0.7;
backgroundIdx = single(12);
AudioCaptureDuration = 1/classificationRate;
AudioCaptureSamples = fs*AudioCaptureDuration;

% Configure UDP system objects
UDPSend = dsp.UDPSender('RemoteIPPort', 21000, 'RemoteIPAddress', hostIPAddress); %Sends to matlab script to display

sizeofFloatInBytes = 4;
numUDPPackets = 3; % This is in sync with the UDPReceiver at host end
UDPReceive = dsp.UDPReceiver('LocalIPPort', 26000, ...  %Receives from EXE
    'MessageDataType', 'single', ...
    'MaximumMessageLength', AudioCaptureSamples, ...
    'ReceiveBufferSize', (AudioCaptureSamples*numUDPPackets)*sizeofFloatInBytes);

% Defining and Initializing History Buffers
probBuffer = single(zeros([NumLabels,classificationRate/2]));
YBuffer = single(backgroundIdx * ones(1, classificationRate/2)); %"background" --> 12

% Create audio buffer
audioBuffer = dsp.AsyncBuffer(fs);
y = zeros(fs, 1, 'single');

% Speech Command Recognition
while true
    % Capture and Buffer Audio
    x = UDPReceive();
    
    if(~isempty(x))
        % Buffer audio in 1s buffer y
        x = x(1:AudioCaptureSamples, 1);
        write(audioBuffer,x);
        y = read(audioBuffer,fs,fs-AudioCaptureSamples);
        
        % Extract Features
        features = extractSpeechFeatures(y);
        
        % Take the log.
        features = log10(features + 1e-6);
        spec = features';
        
        % Predict Speech Commmand
        % features must have known size to generate code for predict()
        features = features(1:98, 1:50);
        
        probs = predict(trainedNet, features);
        [~, YPredicted] = max(probs);
        
        % Statistical Post Processing
        % Keeping history
        YBuffer = [YBuffer(2:end),YPredicted];
        probBuffer = [probBuffer(:,2:end),probs(:)];
        
        [YMode_idx, count] = mode(YBuffer);
        count = single(count);
        maxProb = max(probBuffer(YMode_idx,:));
        
        if (YMode_idx == backgroundIdx || count < countThreshold || maxProb < probThreshold)
            speechCommandIdx = backgroundIdx;
        else
            speechCommandIdx = YMode_idx;
        end
        
        UDPSend([spec(:); speechCommandIdx]);
    end
end
end
