%% Multicore Simulation of Acoustic Beamforming Using a Microphone Array
% This example shows how to beamform signals received by an array of
% microphones to extract a desired speech signal in a noisy environment. It
% uses the dataflow domain in Simulink(R) to partition the data-driven
% portions of the system into multiple threads and thereby improving the
% performance of the simulation by executing it on your desktop's multiple
% cores.

% Copyright 2018-2020 The MathWorks, Inc.

%% Introduction
% The model simulates receiving three audio signals from different
% directions on a 10-element uniformly linear microphone array (ULA). After
% the addition of thermal noise at the receiver, beamforming is applied and
% the result played on a sound device.
model_name = 'slexDataflowAudioBeamforming';
open_system(model_name);

%% Received Audio Simulation
% The Audio Sources subsystem reads from audio files and specifies the
% direction for each audio source. The Wideband Rx Array block simulates
% receiving audio signals at the ULA. The first input to the Wideband Rx
% Array block is a 1000x3 matrix, where the three columns of the input
% correspond to the three audio sources. The second input (Ang) specifies
% the incident direction of the signals. The first row of Ang specifies the
% azimuth angle in degrees for each signal and the second row specifies the
% elevation angle in degrees for each signal. The output of this block is a
% 1000x10 matrix. Each column of the output corresponds to the audio
% recorded at each element of the microphone array. The microphone array's
% configuration is specified in the Sensor Array tab of the block dialog
% panel. The Receiver Preamp block adds white noise to the received
% signals.
open_system([model_name '/Audio Sources']);

%% Beamforming
% There are three Frost Beamformer blocks that perform beamforming on the
% matrix passed via the input port X along the direction specified by the
% input port Ang. Each of the three beamformers steers their beam towards
% one of the three sources. The output of the beamformer is played in the
% Audio Device Writer block. Different sources can be selected using the
% Select Source block.
open_system([model_name '/Dataflow Subsystem']);

%% Improve Simulation Performance Using Multithreading
% This example can use the dataflow domain in Simulink to automatically
% partition the data-driven portions of the system into multiple threads
% and thereby improving the performance of the simulation by executing it
% on your desktop's multiple cores. To learn more about dataflow and how to
% run Simulink models using multiple threads,
% see <docid:dsp_ug#mw_ba342715-0088-4475-add2-80ba2e6fe387 |Dataflow Introduction|>.

%% Setting up Dataflow Subsystem
% In Simulink, you specify dataflow as the execution domain for a subsystem
% by setting the Domain parameter to Dataflow using Property Inspector.
% Dataflow domains automatically partition your model and simulate the
% system using multiple threads for better simulation performance. Once you
% set the Domain parameter to Dataflow, you can use Dataflow Simulation
% Assistant to analyze your model to get better performance. You can open
% the Dataflow Simulation Assistant by clicking on the *Dataflow
% assistant* button below the *Automatic frame size calculation* parameter
% in Property Inspector.
%
% <<../slexDataflowAudioBeamforming_PI.png>>
%
% <<../slexMicrophoneBeamformer_assistant_01.png>>
%

%% Analyzing Concurrency in Dataflow Subsystem
% The Dataflow Simulation Assistant suggests changing model settings for
% optimal simulation performance. To accept the proposed model settings,
% next to *Suggested model settings for simulation performance*, click
% *Accept all*. Alternatively, you can expand the section to change the
% settings individually. In this example the model settings are already
% optimal.
% In the Dataflow Simulation Assistant, click the *Analyze* button to start
% the analysis of the dataflow domain for simulation performance. Once the
% analysis is finished, the Dataflow Simulation Assistant shows how many
% threads the dataflow subsystem will use during simulation.
%
% <<../slexMicrophoneBeamformer_assistant_02.png>>
%

%%
% For this model the assistant shows three threads because the three Frost
% Beamformer blocks are computationally intensive and they can run in
% parallel. However, the three Frost Beamformer blocks depend on the
% Microphone Array and Receiver blocks to finish before they start
% execution. Concurrency can be increased for this model by using pipeline
% delays between the beamformer blocks and the source simulation blocks.
% Dataflow Simulation Assistant shows the recommended number of pipeline
% delays as *Suggested Latency*. For this model, the suggested latency is
% one. Click the *Accept* button next to *Suggested Latency* in the
% Dataflow Simulation Assistant to use the recommended latency for the
% Dataflow Subsystem.

%% Multicore Simulation Performance
% To measure performance improvement gained by using dataflow, compare
% execution time of the model with and without dataflow. The Audio Device
% Writer runs in real time and limits the simulation speed of the model to
% real time. Comment out the Audio Device Writer block when measuring
% execution time. On a Windows desktop computer with Intel(R) Xeon(R) CPU
% W-2133 @ 3.6 GHz 6 Cores 12 Threads processor this model using
% dataflow domain executes 1.8x times faster compared to original model.

%% Summary
% This example showed how to beamform signals received by an array of
% microphones to extract a desired speech signal in a noisy environment. It
% also shows how to use the dataflow domain to automatically partition the
% data-driven part of the model into concurrent execution threads and run
% the model using multiple threads.
close_system(model_name, 0);
