SPARK Audio Core
Integrating the Audio Core is particularly useful for testing a SPARK Audio app or a custom app without the need to implement all the complex details involved in handling audio transfers and packets. To achieve this integration, it is necessary to implement the backend that manages audio functionality.
Note
Integrating the Audio Core is optional and only necessary if audio applications are being developed.
Implement the Backend
To ensure proper integration of the Audio Core on custom hardware, a backend that supports audio data flow and codec operations must be developed. This requires implementing the necessary function prototypes defined in core/audio/sac_hal_facade.h.
An example of how to implement the Endpoint Interface is described below.
/** @brief Initialize the audio endpoint interfaces.
*
* @param[out] producer_iface Producer audio endpoint interface.
* @param[out] consumer_iface Consumer audio endpoint interface.
*/
void sac_facade_audio_endpoint_init(sac_endpoint_interface_t *producer_iface, sac_endpoint_interface_t *consumer_iface);
Handling CDC is a key part of the Audio Core, as it ensures proper audio data synchronization across different clock domains. CDC functions are included in the facade to support both the PLL-based approach used by the Quasar board and the packet interpolation approach used by the EVK1.4 board, providing flexibility for different hardware setups.
/** @brief Initialize the Clock Drift Compensation processing stage.
*
* @param[in] format Audio sample format used in the CDC processing.
* @param[out] status Status code.
* @return Reference to the initialized CDC processing stage.
*/
sac_processing_t *sac_facade_cdc_processing_init(sac_sample_format_t format, sac_status_t *status);
/** @brief Format the Clock Drift Compensation statistics as a string of characters.
*
* @param[out] buffer Buffer where to put the formatted string.
* @param[in] size Size of the buffer.
* @param[out] status Status code.
* @return The formatted string length, excluding the NULL terminator.
*/
int sac_facade_cdc_format_stats(char *buffer, uint16_t size, sac_status_t *status);
Implement the Endpoint Interface
To manage audio data flow, the producer and consumer endpoint interfaces require three key actions: one for packet reception or transmission, and two for starting and stopping processes. Refer to the Audio Endpoint section in the Audio Core documentation for more details.
Below is an implementation example for the Quasar board.
Quasar Endpoints Interface implementation example
Implement three functions to perform the three key actions for both the producer and consumer.
Handle packet reception and transmission :
/** @brief Produce Endpoint of the audio codec. * * @param[in] instance Endpoint instance (not used). * @param[out] samples Location to put produced samples. * @param[in] size Size of samples to produce in bytes. * @return Number of bytes produced (always 0 since production is delayed). */ static uint16_t ep_i2s_action_produce(void *instance, uint8_t *samples, uint16_t size) { (void)instance; quasar_audio_sai_read_non_blocking(samples, size); return 0; }
/** @brief Consume Endpoint of the audio codec. * * @param[in] instance Endpoint instance (not used). * @param[in] samples Samples to consume. * @param[in] size Size of samples to consume in bytes. * @return Number of bytes consumed (always 0 since consumption is delayed). */ static uint16_t ep_i2s_action_consume(void *instance, uint8_t *samples, uint16_t size) { (void)instance; quasar_audio_sai_write_non_blocking(samples, size); return 0; }
Start the process :
/** @brief Start the endpoint when used as a producer. * * @param[in] instance Endpoint instance (not used). */ static void ep_i2s_start_produce(void *instance) { (void)instance; quasar_audio_sai_start_read_non_blocking(); }
/** @brief Start the endpoint when used as a consumer. * * @param[in] instance Endpoint instance (not used). */ static void ep_i2s_start_consume(void *instance) { (void)instance; quasar_audio_sai_start_write_non_blocking(); }
Stop the process :
/** @brief Stop the endpoint when used as a producer. * * @param[in] instance Endpoint instance (not used). */ static void ep_i2s_stop_produce(void *instance) { (void)instance; quasar_audio_sai_stop_read_non_blocking(); }
/** @brief Stop the endpoint when used as a consumer. * * @param[in] instance Endpoint instance (not used). */ static void ep_i2s_stop_consume(void *instance) { (void)instance; quasar_audio_sai_stop_write_non_blocking(); }
Assign these functions to their respective endpoint interfaces.
codec_producer_iface->action = ep_i2s_action_produce;
codec_producer_iface->start = ep_i2s_start_produce;
codec_producer_iface->stop = ep_i2s_stop_produce;
}
if (codec_consumer_iface != NULL) {
codec_consumer_iface->action = ep_i2s_action_consume;
codec_consumer_iface->start = ep_i2s_start_consume;
codec_consumer_iface->stop = ep_i2s_stop_consume;
}
}
/* PRIVATE FUNCTIONS **********************************************************/
/** @brief Produce Endpoint of the audio codec.
*