Audio Core API

The Audio Core API is the set of public functions that applications can use to access the Audio Core functionalities.

Initialization

The Audio Core initialization steps are the same for every application. Only the configuration supplied at each step is different depending on specific application needs. Here is a flowchart of the whole initialization process.

Figure not found: Audio Core initialization flowchart

Audio Core Configuration

typedef struct sac_cfg {
    /*! Memory pool instance from which memory allocation is done. */
    uint8_t *memory_pool;
    /*! Memory pool size in bytes. */
    size_t memory_pool_size;
} sac_cfg_t;
memory_pool

This is the chunk of memory the Audio Core uses when creating (or allocating) structures like the ones for the pipelines, endpoints and processing stages as well as the audio buffers. It works much like the C Heap, and enables the Audio Core to internally manage the memory.

memory_pool_size

This is the size in bytes of the memory pool.

Audio Pipeline Configuration

typedef struct sac_pipeline_cfg {
    /*! Set to true if an audio clock drift compensation processing stage will be added to this pipeline. */
    bool cdc_enable;
    /*! Wait for the consumer queue (TX audio buffer) to be full before starting to consume. */
    bool do_initial_buffering;
    /*! Configure the pipeline with mixer's specific options. */
    sac_mixer_option_t mixer_option;
} sac_pipeline_cfg_t;
cdc_enable

This controls if additional memory is allocated or not for the pipeline’s consumer endpoint’s audio buffer to support audio clock drifting compensation. This is required when using the CDC processing stage supplied with the Audio Core. If set to true, the audio buffer capacity is increased by 3 audio packets. See Clock Drift Compensation for more details.

do_initial_buffering

This controls if initial buffering is enabled or not. If set to true, the endpoint’s consumer queue needs to completely fill up once before the endpoint starts consuming audio packets from it. Its purpose is to build the wireless system’s audio latency. It must be enabled on the audio pipeline transmitting audio over-the-air (i.e. the pipeline that has the Wireless Core endpoint as consumer).

mixer_option

This controls the audio pipeline’s audio mixing behavior. If input_mixer_pipeline is set to true, it means the audio pipeline audio stream is to be mixed with another one. If output_mixer_pipeline is set to true, it means the audio pipeline will be mixing audio streams. Both option are mutually exclusive. If a regular audio pipeline is desired (i.e. without audio mixing), both options must be set to false.

Audio Endpoint Configuration

typedef struct sac_endpoint_cfg {
    /*!
     * True if the endpoint produces or consumes audio packets (SAC header + audio payload),
     * False for only audio payloads (audio samples).
     */
    bool use_encapsulation;
    /*! True if the endpoint requires a complete cycle to produce or consume data. False if the endpoint produces or consumes instantly. */
    bool delayed_action;
    /*! 1 if the endpoint produces or consumes mono audio payloads and 2 for interleaved stereo. */
    uint8_t channel_count;
    /*! Bit depth of samples the endpoint produces or consumes. */
    sac_bit_depth_t bit_depth;
    /*! Size in bytes of the audio payload. */
    uint16_t audio_payload_size;
    /*! Size in number of audio packets the endpoint's queue can contain. */
    uint8_t queue_size;
} sac_endpoint_cfg_t;
use_encapsulation

This is to specify if the endpoint deals with encapsulated audio samples or not. For example, a regular hardware audio codec will not produce nor consume encapsulated audio samples but the SPARK Wireless Core will.

delayed_action

This is to specify if the endpoint produces or consumes audio samples instantly or not. In general, an endpoint that uses DMA for audio samples transfers will have delayed_action set to true because after returning from a call to sac_pipeline_produce() or sac_pipeline_consume(), the audio samples transfer will not have completed yet. If using the SPARK Wireless Core endpoints supplied with the SPARK SDK, this settings must be set to false.

channel_count

This is the number of audio channels the endpoint produces or consumes. For mono, this must be set to 1. For interleaved stereo, this must be set to 2.

bit_depth

This is the bit depth of the audio samples the endpoint produces or consumes. Valid values are SAC_16BITS, SAC_20BITS, SAC_24BITS, and SAC_32BITS.

audio_payload_size

This is the size of an audio payload in bytes. For example, if an endpoint produces 20 16-bit samples, this value would be set to 40. Note that if the bit depth is higher than 16 bits (i.e. 20 or 24 bits), the audio_payload_size must take into account the required padding (internal processing will be done on 32-bit values). For example, if an endpoint produces those same 20 samples, but with a bit depth of 24 bits, this value would be set to 80 instead of 40 (20 * 4 bytes).

queue_size

This is the size of the audio buffer in number of audio packets. For a consumer endpoint, this represents most of the latency of the audio pipeline. For a producer endpoint, this represents the size of the queue used for audio processing and should always be set to SAC_MIN_PRODUCER_QUEUE_SIZE unless there is a specific reason to increase it.

Hardware Abstraction Layer

The Hardware Abstraction Layer (HAL) is the set of hardware-dependent functions needed by the Audio Core to operate.

typedef struct sac_hal {
    /*! Function the audio core uses to enter a critical section of the code. */
    void (*enter_critical)(void);
    /*! Function the audio core uses to exit a critical section of the code. */
    void (*exit_critical)(void);
} sac_hal_t;
enter_critical

This is the function called by the Audio Core when it enters a critical section of the code that must not be interrupted. This function needs to disable all interrupts.

exit_critical

This is the function called by the Audio Core when it leaves a critical section of the code that must not be interrupted. This functions needs to re-enable all interrupts disabled by enter_critical.

Statistics

The Audio Core provides pipeline-level statistics that the application can use to monitor the status of the payloads it sends and receives. The available statistics are as follows:

typedef struct sac_statistics {
    /*! Number of audio packets currently in the producer queue. */
    uint32_t producer_buffer_load;
    /*! Maximum number of audio packets the producer queue can hold. */
    uint16_t producer_buffer_size;
    /*! Number of times the producer queue has overflowed. */
    uint32_t producer_buffer_overflow_count;
    /*! Number of corrupted packets received from the coord. */
    uint32_t producer_packets_corrupted_count;
    /*! Number of audio packets currently in the consumer queue. */
    uint32_t consumer_buffer_load;
    /*! Maximum number of audio packets the consumer queue can hold. */
    uint16_t consumer_buffer_size;
    /*! Number of times the consumer queue has overflowed. */
    uint32_t consumer_buffer_overflow_count;
    /*! Number of times the consumer queue has underflowed. */
    uint32_t consumer_buffer_underflow_count;
    /*! Consumer queue peak load. */
    uint32_t consumer_queue_peak_buffer_load;
    /*! Consumer link margin min. */
    uint32_t consumer_link_margin_min_peak;
    /*! Consumer CCA count peak. */
    uint32_t consumer_cca_fail_count_peak;
    /*! Number of packets inflated by the CDC. */
    uint32_t cdc_inflated_packets_count;
    /*! Number of packets deflated by the CDC. */
    uint32_t cdc_deflated_packets_count;
} sac_statistics_t;

To refresh the statistics, the following function must be called:

sac_statistics_t *sac_pipeline_update_stats(sac_pipeline_t *pipeline);

This function returns a pointer to the statistics for direct manipulation by the application. The following code snippet gives an example on how to access the consumer_buffer_overflow_count counter:

uint32_t buf_overflow;
sac_statistics_t *stats;

stats = sac_pipeline_update_stats(pipeline);

buf_overflow = stats->consumer_buffer_overflow_count;

To reset the statistics, the user can simply call:

void sac_pipeline_reset_stats(sac_pipeline_t *pipeline);

This will reset all the statistics counters to 0. If using the Audio Core in a wireless application, resetting the statistics just after the link has synchronized is recommended as accumulated statistics prior to that point are mostly irrelevant.

Finally, a function that formats a string with all the available statistics is available:

int sac_pipeline_format_stats(sac_pipeline_t *pipeline, char *buffer, uint16_t size);

This functions adds the pipeline’s name to the string in order to separate the statistics by pipeline. This is particularly useful on systems using many pipelines. Before calling sac_pipeline_format_stats(), the statistics must be updated with sac_pipeline_update_stats() as shown in the following example:

char stats_string[500];

sac_pipeline_update_stats(pipeline);
sac_pipeline_format_stats(pipeline, stats_string, sizeof(stats_string));
puts(stats_string);

Reference

sdk_spark_vx.y.z/
└── core/
    └── audio/
        ├── sac_api.h
        ├── sac_error.h
        ├── sac_stats.h
        └── sac_utils.h

File name

Description

sac_api.h

The API itself. This header file must be included in the user’s application in order to use the Audio Core.

sac_error.h

Audio Core error codes.

sac_stats.h

Audio Core statistics module.

sac_utils.h

Audio Core utility functions.