C++ API Reference¶
MicArray¶
-
template<unsigned MIC_COUNT, class TDecimator, class TPdmRx, class TSampleFilter, class TOutputHandler>
class MicArray¶ Represents the microphone array component of an application.
- Template Parameters:
MIC_COUNT – Number of microphone output channels from the the mic array component
TDecimator – Type for the decimator. See Decimator.
TPdmRx – Type for the PDM rx service used. See PdmRx.
TSampleFilter – Type for the output filter used. See SampleFilter.
TOutputHandler – Type for the output handler used. See OutputHandler.
Public Functions
-
inline MicArray()¶
Construct a
MicArray.This constructor uses the default constructor for each of its components, PdmRx, Decimator, SampleFilter, and OutputHandler.
-
void ThreadEntry()¶
Entry point for the decimation thread.
This function does not return. It loops indefinitely, collecting blocks of PDM data from PdmRx (which must have already been started), uses Decimator to filter and decimate the sample stream to the output sample rate, applies any post-processing with SampleFilter, and then delivers the stream of output samples through OutputHandler.
Public Members
-
TPdmRx PdmRx¶
The PDM rx service.
The template parameter
TPdmRxis the concrete class implementing the microphone array’s PDM rx service, which is responsible for collecting PDM samples from a port and delivering them to the decimation thread.TPdmRxis only required to implement one function,GetPdmBlock():uint32_t* GetPdmBlock();
GetPdmBlock()returns a pointer to a block of PDM data, formatted as expected by the decimator.GetPdmBlock()is called from the decimator thread and is expected to block until a new full block of PDM data is available to be decimated.For example, StandardPdmRxService::GetPdmBlock() waits to receive a pointer to a block of PDM data from a streaming channel. The pointer is sent from the PdmRx interrupt (or thread) when the block has been completed. This is used for capturing PDM data from a port.
-
TDecimator Decimator¶
The Decimator.
The template parameter
TDecimatoris the concrete class implementing the microphone array’s decimation procedure.TDecimatoris only required to implement one function,ProcessBlock():void ProcessBlock( int32_t sample_out[MIC_COUNT], uint32_t *pdm_block);
ProcessBlock()takes a block of PDM samples via itspdm_blockparameter, applies the appropriate decimation logic, and outputs a single (multi-channel) sample sample via itssample_outparameter. The size and formatting of the PDM block expected by the decimator depends on its particular implementation.
-
TSampleFilter SampleFilter¶
The output filter.
The template parameter
TSampleFilteris the concrete class implementing the microphone array’s sample filter component. This component can be used to apply additional non-decimating, non-interpolating filtering of samples.TSampleFilter()is only required to implement one function,Filter():void Filter(int32_t sample[MIC_COUNT]);
Filter()takes a single (multi-channel) sample from the decimator component’s output and may update the sample in-place.For example a sample filter based on the DcoeSampleFilter class template applies a simple first-order IIR filter to the output of the decimator, in order to eliminate the DC component of the audio signals.
If no additional filtering is required, the NopSampleFilter class template can be used for
TSampleFilter, which leaves the sample unmodified. In this case, it is expected that the call to NopSampleFilter::Filter() will ultimately get completely eliminated at build time. That way no addition run-time compute or memory costs need be introduced for the additional flexibility.Even though
TDecimatorandTSampleFilterboth (possibly) apply filtering, they are separate components of theMicArraybecause they are conceptually independent.
-
TOutputHandler OutputHandler¶
The output handler.
The template parameter
TOutputHandleris the concrete class implementing the microphone array’s output handler component. After the PDM input stream has been decimated to the appropriate output sample rate, and after any post-processing of that output stream by the sample filter, the output samples must be delivered to another thread for any additional processing. It is the responsibility of this component to package and deliver audio samples to subsequent processing stages.TOutputHandleris only required to implement one function,OutputSample():void OutputSample(int32_t sample[MIC_COUNT]);
OutputSample()is called exactly once for each mic array output sample.OutputSample()may block if necessary until the subsequent processing stage ready to receive new data. However, the decimator thread (in whichOutputSample()is called) as a whole has a real-time constraint - it must be ready to pull the next block of PDM data while it is available.
StandardPdmRxService¶
-
struct pdm_rx_isr_context_t¶
PDM rx interrupt configuration and context.
Public Members
-
port_t p_pdm_mics¶
Port on which PDM samples are received.
-
uint32_t *pdm_buffer[2]¶
Pointers to a pair of buffers used for storing captured PDM samples.
The buffers themselves are allocated by the application and passed to mic_array::StandardPdmRxService::Init The idea is that while the PDM rx ISR is filling one buffer, the decimation thread is busy processing the contents of the other buffer. If the real-time constraint is maintained, the decimation thread will be finished with the contents of its buffer before the PDM rx ISR fills the other buffer. Once full, the PDM rx ISR does a double buffer pointer swap and hands the newly-filled buffer to the decimation thread.
-
unsigned phase¶
Tracks the completeness of the buffer currently being filled.
Each read of samples from
p_pdm_micsgives one word of data. This variable tracks how many more port reads are required before the current buffer has been filled.
-
unsigned phase_reset¶
The number of words to read from
p_pdn_micsto fill a buffer.
-
chanend_t c_pdm_data¶
Streaming chanend the PDM rx ISR uses to signal the decimation thread that another buffer is full and ready to be processed.
The streaming channel itself is allocated by mic_array::StandardPdmRxService, which owns the other end of the channel.
-
unsigned credit¶
Used for detecting when the real-time constraint is violated by the decimation thread.
Each time the decimation thread is given a block of PDM data to process,
creditis reset to2. Each time the PDM rx ISR hands a block of PDM data to the decimation thread, this is decremented.- Deadlock Condition
mic_array::StandardPdmRxService uses a streaming channel to facilitate communication between the two execution contexts used by the mic array, the decimation thread and the PDM rx ISR. A streaming channel is used because it allows the contexts to operate asynchronously.
A channel has a 2 word buffer, and as long as there is room in the buffer, an
OUTinstruction putting a word (in this case, a pointer) into the channel is guaranteed not to block. This is important because the PDM rx ISR is typically configured on the same hardware thread as the decimation thread.If a thread is blocked on an
OUTinstruction to a channel, in order to unblock the thread, anINmust be issued on the other end of that channel. But because the PDM rx ISR is blocked, it cannot hand control back to the decimation thread, which means the decimation thread can never issue anINinstruction to unblock the ISR. The result is a deadlock.Unfortunately, there is no way for a thread to query a chanend to determine whether it will block if an
OUTinstruction is issued. That is whycreditis used. Before issuing anOUTtoc_pdm_data, the PDM rx ISR checks whethercreditis non-zero. If so, the ISR issues theOUTinstruction as normal and decrementscredit.If
creditis zero, the default behavior of PDM rx ISR is to raise an exception (ET_ECALL). This reflects the idea that it is generally better if system-breaking errors loudly announce themselves (at least by default). If using mic_array::StandardPdmRxService, this behavior can be changed by passingfalsein a call to mic_array::StandardPdmRxService::AssertOnDroppedBlock(), which will allow blocks of PDM data to be silently dropped (while still avoiding a permanent deadlock).
-
unsigned missed_blocks¶
Controls and records anti-deadlock behavior.
If the PDM rx ISR finds that
creditis0when it’s time to send a filled buffer to the decimation thread, it usesmissed_blocksto control whether the PDM rx ISR should raise an exception or silently drop the block of PDM data.If
missed_blocksis-1(its default value) an exception is raised. Otherwisemissed_blocksis used to record the number of blocks that have been quietly dropped.
-
port_t p_pdm_mics¶
-
pdm_rx_isr_context_t pdm_rx_isr_context¶
Configuration and context of the PDM rx ISR when mic_array::StandardPdmRxService is used in interrupt mode.
pdm_rx_isr(pdm_rx_isr.S) directly allocates this object as configuration and state parameters required by that interrupt routine.
-
static inline void enable_pdm_rx_isr(const port_t p_pdm_mics)¶
Configure port to use
pdm_rx_isras an interrupt routine.This function configures
p_pdm_micsto usepdm_rx_isras its interrupt vector and enables the interrupt on the current hardware thread.This function does NOT unmask interrupts.
- Parameters:
p_pdm_mics – Port resource to enable ISR on.
-
template<unsigned CHANNELS_IN, unsigned CHANNELS_OUT>
class StandardPdmRxService¶ PDM rx service which collects PDM sample data from a port and uses a streaming channel to send a block of data by pointer further down the mic array pipeline.
This class template is intended to be used for the
TPdmRxtemplate parameter of MicArray, where it represents the MicArray::PdmRx component of the mic array.This class can run the PDM rx service either as a stand-alone thread or through an interrupt.
- Inter-context Transfer
A streaming channel is used to transfer control of the PDM data block between execution contexts (i.e. thread->thread or ISR->thread).
The mic array unit receives blocks of PDM data from an instance of this class by calling GetPdmBlock(), which blocks until a new PDM block is available.
StandardPdmRxServicecollects blocks of PDM samples from a port and makes them available to the decimation thread as the blocks are completed.This class provides the logic for aggregating PDM data taken from a port into blocks, and provides methods
ReadPort(),SendBlock()andGetPdmBlock().ReadPort()is responsible for reading 1 word of data fromp_pdm_mics.SendBlock()is provided a block of PDM data as a pointer and is responsible for signaling that to the subsequent processing stage.ReadPort()andSendBlock()are used byStandardPdmRxServiceitself (when running as a thread, rather than ISR).GetPdmBlock()is responsible for receiving a block of PDM data fromSendBlock()as a pointer, deinterleaving the buffer contents, and returning a pointer to the PDM data in the format expected by the mic array unit’s decimator component. SeeGetPdmBlock()is called by the decimation thread. The pair of functions,SendBlock()andGetPdmBlock()facilitate inter-thread communication,SendBlock()being called by the transmitting end of the communication channel, andGetPdmBlock()being called by the receiving end.- Layouts
The buffer transferred by
SendBlock()containsCHANNELS_IN * this->pdm_out_words_per_channelwords of PDM data forCHANNELS_INmicrophone channels. The words are stored in reverse order of arrival.See
mic_array::deinterleave_pdm_samples()for additional details on this format.Within
GetPdmBlock()(i.e. mic array thread) the PDM data block is deinterleaved and copied to another buffer in the format required by the decimator component, which is returned byGetPdmBlock(). This buffer containsCHANNELS_OUT * this->pdm_out_words_per_channelwords forCHANNELS_OUTmicrophone channels.
- Channel Filtering
In some cases an application may be required to capture more microphone channels than should actually be processed by subsequent processing stages (including the decimator component). For example, this may be the case if 4 microphone channels are desired but only an 8 bit wide port is physically available to capture the samples.
This class template has a parameter both for the number of channels to be captured by the port (
CHANNELS_IN), as well as for the number of channels that are to be output for consumption by theMicArray’s decimator component (CHANNELS_OUT).When the PDM microphones are in an SDR configuration,
CHANNELS_INmust be the width (in bits) of the XCore port to which the microphones are physically connected. When in a DDR configuration,CHANNELS_INmust be twice the width (in bits) of the XCore port to which the microphones are physically connected.CHANNELS_OUTis the number of microphone channels to be consumed by the mic array’s decimator component (i.e. must be the same as theMIC_COUNTtemplate parameter of the decimator component). If all port pins are connected to microphones, this parameter will generally be the same asCHANNELS_IN.
- Channel Index (Re-)Mapping
-
The input channel index of a microphone depends on the pin to which it is connected. Each pin connected to a port has a bit index for that port, given in the ‘Signal Description and GPIO’ section of your package’s datasheet.
Suppose an
N-bit port is used to capture microphone data, and a microphone is connected to bitBof that port. In an SDR microphone configuration, the input channel index of that microphone isB, the same as the port bit index.In a DDR configuration, that microphone will be on either input channel index
BorB+N, depending on whether that microphone is configured for in-phase capture or out-of-phase capture.Sometimes it may be desirable to re-order the microphone channel indices. This is likely the case, for example, when
CHANNELS_IN > CHANNELS_OUT.By default output channels are mapped from the input channels with the same index. If
CHANNELS_IN > CHANNELS_OUT, this means that the input channels with the highestCHANNELS_IN-CHANNELS_OUTindices are dropped by default.The
MapChannel()andMapChannels()methods can be used to specify a non-default mapping from input channel indices to output channel indices. It takes a pointer to aCHANNELS_OUT-element array specifying the input channel index for each output channel.
- Template Parameters:
CHANNELS_IN – The number of microphone channels to be captured by the port. For example, if using a 4-bit port to capture 6 microphone channels in a DDR configuration (because there are no 3 or 6 pin ports)
CHANNELS_INshould be8, because that’s how many must be captured, even if two of them are stripped out before passing audio frames to subsequent application stages.CHANNELS_OUT – The number of output microphone channels to be delivered by this
StandardPdmRxServiceinstance.
Public Functions
-
uint32_t ReadPort()¶
Read a word of PDM data from the port.
- Returns:
A
uint32_tcontaining 32 PDM samples. IfMIC_COUNT >= 2the samples from each port will be interleaved together.
-
void SendBlock(uint32_t *block)¶
Send a block of PDM data to a listener.
- Parameters:
block – PDM data to send.
-
void Init(port_t p_pdm_mics, pdm_rx_conf_t &pdm_rx_config)¶
Initialize the PDM RX service.
Sets the input port and binds application-provided buffers from pdm_rx_conf_t
pdm_rx_config.Requirements:
pdm_rx_config.pdm_in_double_bufmust be sized 2 * CHANNELS_IN *pdm_rx_config.pdm_out_words_per_channelwords and remain valid for the lifetime of the service.pdm_rx_config.pdm_out_blockmust be sized CHANNELS_OUT *pdm_rx_config.pdm_out_words_per_channelwords and remain valid for the lifetime of the service.
- Parameters:
p_pdm_mics – Port from which PDM samples are captured.
pdm_rx_config – PDM RX configuration
-
void MapChannels(const unsigned map[CHANNELS_OUT])¶
Set the input-output mapping for all output channels.
By default, input channel index
kmaps to output channel indexk.This method overrides that behavior for all channels, re-mapping each output channel such that output channel
kis derived from input channelmap[k].Note
Changing the channel mapping while the mic array unit is running is not recommended.
- Parameters:
map – Array containing new channel map.
-
void MapChannel(unsigned out_channel, unsigned in_channel)¶
Set the input-output mapping for a single output channel.
By default, input channel index
kmaps to output channel indexk.This method overrides that behavior for a single output channel, configuring output channel
out_channelto be derived from input channelin_channel.Note
Changing the channel mapping while the mic array unit is running is not recommended.
- Parameters:
out_channel – Output channel index to be re-mapped.
in_channel – New source channel index for
out_channel.
-
void InstallISR()¶
Install ISR for PDM reception on the current core.
Note
This does not unmask interrupts.
-
void UnmaskISR()¶
Unmask interrupts on the current core.
-
uint32_t *GetPdmBlock()¶
Get a block of PDM data.
Because blocks of PDM samples are delivered by pointer, the caller must either copy the samples or finish processing them before the next block of samples is ready, or the data will be clobbered.
Note
This is a blocking call.
- Returns:
Pointer to block of PDM data.
-
void AssertOnDroppedBlock(bool doAssert)¶
Set whether dropped PDM samples should cause an assertion.
If
doAssertis set totrue(default), the PDM rx ISR will raise an exception (ET_CALL) if it is ready to deliver a PDM block to the mic array thread when the mic array thread is not ready to receive it. Iffalse, dropped blocks can be tracked throughpdm_rx_isr_context.missed_blocks.
-
void SetPort(port_t p_pdm_mics)¶
Set the port from which to collect PDM samples.
-
void ThreadEntry()¶
Entry point for PDM processing thread.
This function loops forever, performing a port read and if a new block has completed, signal a block send, every iteration.
TwoStageDecimator¶
-
template<unsigned MIC_COUNT>
class TwoStageDecimator¶ First and Second Stage Decimator.
This class template represents a two stage decimator which converts a stream of PDM samples to a lower sample rate stream of PCM samples.
Concrete implementations of this class template are meant to be used as the
TDecimatortemplate parameter in the MicArray class template.- Template Parameters:
MIC_COUNT – Number of microphone channels.
Public Functions
-
void Init(mic_array_decimator_conf_t &decimator_conf)¶
Initialize the two-stage decimator from a configuration struct mic_array_decimator_conf_t
decimator_conf.Reads stage-1 and stage-2 filter parameters from
decimator_confand prepares internal state: The caller must ensure all pointers insidedecimator_conf.filter_conf[0] anddecimator_conf.filter_conf[0] are valid and persist for the lifetime of the decimator.- Parameters:
decimator_conf – Decimator pipeline configuration.
-
void ProcessBlock(int32_t sample_out[MIC_COUNT], uint32_t *pdm_block)¶
Process one block of PDM data.
Processes a block of PDM data to produce an output sample from the second stage decimator.
pdm_blockcontains exactly enough PDM samples to produce a single output sample from the second stage decimator. The layout ofpdm_blockshould (effectively) be:struct { struct { // lower word indices are older samples. // less significant bits in a word are older samples. uint32_t samples[S2_DEC_FACTOR]; } microphone[MIC_COUNT]; // mic channels are in ascending order } pdm_block;
A single output sample from the second stage decimator is computed and written to
sample_out[].- Parameters:
sample_out – Output sample vector.
pdm_block – PDM data to be processed.
Public Members
-
const uint32_t *filter_coef¶
Pointer to filter coefficients for Stage 1
-
uint32_t *pdm_history_ptr¶
Pointer to filter state (PDM history) for stage-1 filter.
-
unsigned pdm_history_sz¶
Per-mic channel filter state (PDM history) size in 32-bit words for stage-1 filter.
-
unsigned decimation_factor¶
Stage 2 filter decimation factor.
SampleFilter¶
NopSampleFilter¶
-
template<unsigned MIC_COUNT>
class NopSampleFilter¶ SampleFilter which does nothing.
To be used as the
TSampleFiltertemplate parameter of MicArray when no post-decimation filtering is desired.Calls to
NopSampleFilter::Filter()are intended to be optimized out at compile time.- Template Parameters:
MIC_COUNT – Number of microphone channels.
DcoeSampleFilter¶
-
template<unsigned MIC_COUNT>
class DcoeSampleFilter¶ Filter which applies DC Offset Elimination (DCOE).
To be used as the
TSampleFiltertemplate parameter of MicArray when DCOE is desired as post-processing after the decimation filter.The filter is a simple first-order IIR filter which applies the following filter equation:
R = 252.0 / 256.0 y[t] = R * y[t-1] + x[t] - x[t-1]
- Template Parameters:
MIC_COUNT – Number of microphone channels.
Public Functions
-
void Init()¶
Initialize the filter states.
The filter states must be initialized prior to calls to
Filter().
-
void Filter(int32_t sample[MIC_COUNT])¶
Apply DCOE filter on samples.
sampleis an array of samples to be filtered, and is updated in-place.The filter states must have been initialized with a call to
Init()prior to calling this function.- Parameters:
sample – Samples to be filtered. Updated in-place.
OutputHandler¶
An OutputHandler is a class which meets the requirements to be used as the
TOutputHandler template parameter of the
MicArray class template. The basic
requirement is that it have a method:
This method is how the mic array communicates its output with the rest of the application’s audio processing pipeline. MicArray calls this method once for each mic array output sample.
See MicArray::OutputHandler
for more details.
FrameOutputHandler¶
-
template<unsigned MIC_COUNT, unsigned SAMPLE_COUNT, template<unsigned, unsigned> class FrameTransmitter, unsigned FRAME_COUNT = 1>
class FrameOutputHandler¶ OutputHandler implementation which groups samples into non-overlapping multi-sample audio frames and sends entire frames to subsequent processing stages.
This class template can be used as an OutputHandler with the MicArray class template. See MicArray::OutputHandler.
Classes derived from this template collect samples into frames. A frame is a 2 dimensional array with one index corresponding to the audio channel and the other index corresponding to time step, e.g.:
int32_t frame[MIC_COUNT][SAMPLE_COUNT];
Each call to OutputSample() adds the sample to the current frame, and then iff the frame is full, uses its FrameTx component to transfer the frame of audio to subsequent processing stages. Only one of every
SAMPLE_COUNTcalls to OutputSample() results in an actual transmission to subsequent stages.With
FrameOutputHandler, the thread receiving the audio will generally need to know how many microphone channels and how many samples to expect per frame (although, strictly speaking, that depends upon the chosenFrameTransmitterimplementation).- Template Parameters:
MIC_COUNT –
The number of audio channels in each sample and each frame.
SAMPLE_COUNT – Number of samples per frame.
The
SAMPLE_COUNTtemplate parameter is the number of samples assembled into each audio frame. Only completed frames are transmitted to subsequent processing stages. ASAMPLE_COUNTvalue of1effectively disables framing, transmitting one sample for each call made to OutputSample.FrameTransmitter –
The concrete type of the FrameTx component of this class.
FRAME_COUNT –
The number of frame buffers an instance of
FrameOutputHandlershould cycle through. Unless audio frames are communicated with subsequent processing stages through shared memory, the default value of1is usualy ideal.
Public Functions
-
inline FrameOutputHandler()¶
Construct new
FrameOutputHandler.The default no-argument constructor for
FrameTransmitteris used to createFrameTx.
- inline FrameOutputHandler(
- FrameTransmitter<MIC_COUNT, SAMPLE_COUNT> frame_tx,
Construct new
FrameOutputHandler.Uses the provided FrameTransmitter to send frames.
- Parameters:
frame_tx – Frame transmitter for sending frames.
-
bool OutputSample(int32_t sample[MIC_COUNT])¶
Add new sample to current frame and output frame if filled.
- Parameters:
sample – Sample to be added to current frame.
-
void CompleteShutdown()¶
Complete mic array shutdown process.
Public Members
-
FrameTransmitter<MIC_COUNT, SAMPLE_COUNT> FrameTx¶
FrameTransmitterused to transmit frames to the next stage for processing.FrameTransmitteris the template, template parameter used in this class to control how frames of audio data are communicated with subsequent pipeline stages.The type supplied for
FrameTransmittermust be a class template with two integer template parameters, corresponding to this class’sMIC_COUNTandSAMPLE_COUNTtemplate parameters respectively, indicating the shape of the frame object to be transmitted.The
FrameTransmittertype is required to implement a single method:void OutputFrame(int32_t frame[MIC_COUNT][SAMPLE_COUNT]);
OutputFrame()is called once for each completed audio frame and is responsible for the details of how the frame’s data gets communicated to subsequent stages. For example, the ChannelFrameTransmitter class template uses an XCore channel to send samples to another thread (by value).Alternative implementations might use shared memory or an RTOS queue to transmit the frame data, or might even use a port to signal the samples directly to an external DAC.
ChannelFrameTransmitter¶
-
template<unsigned MIC_COUNT, unsigned SAMPLE_COUNT>
class ChannelFrameTransmitter¶ Frame transmitter which transmits frame over a channel.
This class template is meant for use as the
FrameTransmittertemplate parameter of FrameOutputHandler.When using this frame transmitter, frames are transmitted over a channel using the frame transfer API in
mic_array/frame_transfer.h.Usually, a call to
ma_frame_rx()(with the other end of c_frame_out as argument) should be used to receive the frame on another thread.If the receiving thread is not waiting to receive the frame when OutputFrame() is called, that method will block until the frame has been transmitted. In order to ensure there are no violations of the mic array’s real-time constraints, the receiver should be ready to receive a frame as soon as it becomes available.
Frames can be transmitted between tiles using this class.
Note
While OutputFrame() is blocking, it will not prevent the PDM rx interrupt from firing.
- Template Parameters:
MIC_COUNT – Number of audio channels in each frame.
SAMPLE_COUNT – Number of samples per frame.
Public Functions
-
inline ChannelFrameTransmitter()¶
Construct a
ChannelFrameTransmitter.If this constructor is used, SetChannel() must be called to configure the channel over which frames are transmitted prior to any calls to OutputFrame().
-
inline ChannelFrameTransmitter(chanend_t c_frame_out)¶
Construct a
ChannelFrameTransmitter.The supplied value of
c_frame_outmust be a valid chanend.- Parameters:
c_frame_out – Chanend over which frames will be transmitted.
-
void SetChannel(chanend_t c_frame_out)¶
Set channel used for frame transfers.
The supplied value of
c_frame_outmust be a valid chanend.- Parameters:
c_frame_out – Chanend over which frames will be transmitted.
-
chanend_t GetChannel()¶
Get the chanend used for frame transfers.
- Returns:
Channel to be used for frame transfers.
-
bool OutputFrame(int32_t frame[MIC_COUNT][SAMPLE_COUNT])¶
Transmit the specified frame.
See ChannelFrameTransmitter for additional details.
- Parameters:
frame – Frame to be transmitted.
-
void CompleteShutdown()¶
Complete mic array shutdown process by exchanging end tokens with the app. This causes ma_shutdown() to return indicating mic array shutdown completion.
Misc¶
-
template<unsigned MIC_COUNT>
void mic_array::deinterleave_pdm_samples( - uint32_t *samples,
- unsigned s2_dec_factor,
Deinterleave the channels of a block of PDM data.
PDM samples received on a port are shifted into a 32-bit buffer in such a way that the samples for each microphone channel are all interleaved with one another. The first stage decimator, however, requires these to be separated.
samplesmust point to a buffer containing(MIC_COUNT*s2_dec_factor)words of PDM data. Because the decimation factor for the first stage decimator is a fixed value of32,32PDM samples from each microphone is enough to produce one output sample (aMIC_COUNT-element vector) from the first stage decimator.32*s2_dec_factorPDM samples for each of theMIC_COUNTmicrophone channels is then exactly what is required to produce a single output sample from the second stage decimator.The PDM data will be deinterleaved in-place.
On input, the format of the buffer to which
samplespoints is assumed to be such that the following function will extract (only) thekth sample for microphone channeln(wherekis a time index, not a memory index):- Input Format
unsigned get_sample(uint32_t* samples, unsigned MIC_COUNT, unsigned s2_dec_factor, unsigned n, unsigned k) { const end_word = MIC_COUNT * s2_dec_factor - 1; // chronologically first const unsigned samp_per_word = 32 / MIC_COUNT; const words_from_end = k / samp_per_word; const uint32_t word_val = samples[end_word-words_from_end]; const unsigned bit_offset = (k % end_word) + n; return (word_val >> bit_offset) & 1; }
Here, the words of
samplesare stored in reverse order (older samples are at higher word indices), and within a word the oldest samples are the least significant bits. The LSb of a word is always microphone channel0, and the MSb of a word is always microphone channelMIC_COUNT-1.Upon return, the format of the buffer to which samples points will be such that the following function will extract (only) the
kth sample for microphone channeln:- Output Format
unsigned get_sample(uint32_t* samples, unsigned MIC_COUNT, unsigned s2_dec_factor, unsigned n, unsigned k) { const unsigned subblock = (s2_dec_factor-1)-(k/32); const unsigned word_val = samples[subblock * MIC_COUNT + n]; return (word_val >> (k%32)) & 1; }
Here, each word contains samples from only a single channel, with words at higher addresses containing older samples.
samples[0]contains the newest samples for microphone channel0, andsamples[MIC_COUNT-1]contains the newest samples for microphone channelMIC_COUNT-1.samples[MIC_COUNT]contains the next-oldest set of samples for channel0, and so on.- Template Parameters:
MIC_COUNT – Number of channels represented in PDM data. One of
{1,2,4,8}- Parameters:
samples – Pointer to block of PDM samples.
s2_dec_factor – Stage2 decimator decimation factor.