Updated dependencies.
This commit is contained in:
parent
d86c494d45
commit
58748fcef1
101 changed files with 5845 additions and 2391 deletions
|
|
@ -0,0 +1,118 @@
|
|||
/**
|
||||
* @file audio_mixer.h
|
||||
* @brief Mixer interface for esp-audio-player. Provides a global mixer that accepts
|
||||
* PCM from multiple sources via FreeRTOS ring buffers and writes mixed PCM to I2S.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#include "audio_player.h"
|
||||
#include "../audio_decode_types.h" // FIXME: leaks out
|
||||
#include "audio_stream.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configuration structure for the audio mixer
|
||||
*/
|
||||
typedef struct {
|
||||
audio_player_mute_fn mute_fn; /**< Function to mute/unmute audio */
|
||||
audio_reconfig_std_clock clk_set_fn; /**< Function to reconfigure I2S clock */
|
||||
audio_player_write_fn write_fn; /**< Function to write PCM data to I2S */
|
||||
UBaseType_t priority; /**< FreeRTOS task priority for the mixer task */
|
||||
BaseType_t coreID; /**< ESP32 core ID for the mixer task */
|
||||
|
||||
format i2s_format; /**< Fixed output format for the mixer */
|
||||
} audio_mixer_config_t;
|
||||
|
||||
/**
|
||||
* @brief Mixer callback function type
|
||||
*/
|
||||
typedef audio_player_cb_t audio_mixer_cb_t;
|
||||
|
||||
/**
|
||||
* @brief Get the number of active streams in the mixer
|
||||
*
|
||||
* @return Number of active streams
|
||||
*/
|
||||
uint8_t audio_mixer_stream_count();
|
||||
|
||||
/**
|
||||
* @brief Lock the mixer's main mutex
|
||||
*
|
||||
* Call this before modifying stream state (busy flags, queues).
|
||||
*/
|
||||
void audio_mixer_lock();
|
||||
|
||||
/**
|
||||
* @brief Unlock the mixer's main mutex
|
||||
*/
|
||||
void audio_mixer_unlock();
|
||||
|
||||
/**
|
||||
* @brief Add a stream to the mixer's processing list
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*
|
||||
* @param h Handle of the stream to add
|
||||
*/
|
||||
void audio_mixer_add_stream(audio_stream_handle_t h);
|
||||
|
||||
/**
|
||||
* @brief Remove a stream from the mixer's processing list
|
||||
*
|
||||
* This function is thread-safe.
|
||||
*
|
||||
* @param h Handle of the stream to remove
|
||||
*/
|
||||
void audio_mixer_remove_stream(audio_stream_handle_t h);
|
||||
|
||||
/**
|
||||
* @brief Query the current mixer output format
|
||||
*
|
||||
* Returns zeros if the mixer is not initialized.
|
||||
*
|
||||
* @param[out] sample_rate Pointer to store the sample rate
|
||||
* @param[out] bits_per_sample Pointer to store the bits per sample
|
||||
* @param[out] channels Pointer to store the number of channels
|
||||
*/
|
||||
void audio_mixer_get_output_format(uint32_t *sample_rate, uint32_t *bits_per_sample, uint32_t *channels);
|
||||
|
||||
/**
|
||||
* @brief Register a global callback for mixer events
|
||||
*
|
||||
* @param cb Callback function to register
|
||||
*/
|
||||
void audio_mixer_callback_register(audio_mixer_cb_t cb);
|
||||
|
||||
/**
|
||||
* @brief Check if the mixer is initialized
|
||||
*
|
||||
* @return true if initialized, false otherwise
|
||||
*/
|
||||
bool audio_mixer_is_initialized();
|
||||
|
||||
/**
|
||||
* @brief Initialize the mixer and start the mixer task
|
||||
*
|
||||
* @param cfg Pointer to the mixer configuration structure
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid configuration
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_mixer_init(audio_mixer_config_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the mixer and stop the mixer task
|
||||
*/
|
||||
void audio_mixer_deinit();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -152,6 +152,7 @@ typedef enum {
|
|||
typedef esp_err_t (*audio_player_mute_fn)(AUDIO_PLAYER_MUTE_SETTING setting);
|
||||
typedef esp_err_t (*audio_reconfig_std_clock)(uint32_t rate, uint32_t bits_cfg, i2s_slot_mode_t ch);
|
||||
typedef esp_err_t (*audio_player_write_fn)(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms);
|
||||
typedef esp_err_t (*audio_player_write_fn2)(void *audio_buffer, size_t len, size_t *bytes_written, uint32_t timeout_ms, void *ctx);
|
||||
|
||||
typedef struct {
|
||||
audio_player_mute_fn mute_fn;
|
||||
|
|
@ -159,6 +160,10 @@ typedef struct {
|
|||
audio_player_write_fn write_fn;
|
||||
UBaseType_t priority; /*< FreeRTOS task priority */
|
||||
BaseType_t coreID; /*< ESP32 core ID */
|
||||
bool force_stereo; /*< upmix mono -> stereo */
|
||||
|
||||
audio_player_write_fn2 write_fn2;
|
||||
void *write_ctx;
|
||||
} audio_player_config_t;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
* @file audio_stream.h
|
||||
* @brief Stream API — create/delete logical playback streams and control them.
|
||||
* These streams own their decode task and submit PCM to the mixer.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "audio_player.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct audio_stream;
|
||||
/**
|
||||
* @brief Audio stream handle
|
||||
*/
|
||||
typedef struct audio_stream* audio_stream_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Macro to check if a stream handle is valid
|
||||
*/
|
||||
#define CHECK_STREAM(s) \
|
||||
ESP_RETURN_ON_FALSE(s != NULL, ESP_ERR_INVALID_ARG, "audio_stream", "stream is NULL")
|
||||
|
||||
/**
|
||||
* @brief Audio stream types
|
||||
*/
|
||||
typedef enum {
|
||||
AUDIO_STREAM_TYPE_UNKNOWN = 0, /**< Unknown stream type */
|
||||
AUDIO_STREAM_TYPE_DECODER, /**< Stream that decodes audio (e.g., MP3, WAV) */
|
||||
AUDIO_STREAM_TYPE_RAW /**< Stream that accepts raw PCM data */
|
||||
} audio_stream_type_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration structure for an audio stream
|
||||
*/
|
||||
typedef struct {
|
||||
audio_stream_type_t type; /**< Type of stream */
|
||||
char name[16]; /**< Optional: Name of the stream (e.g. "sfx", "bgm"). Auto-generated if empty. */
|
||||
UBaseType_t priority; /**< FreeRTOS task priority for the stream's decoder task (if applicable) */
|
||||
BaseType_t coreID; /**< ESP32 core ID for the stream's decoder task (if applicable) */
|
||||
} audio_stream_config_t;
|
||||
|
||||
/**
|
||||
* @brief Default configuration for an audio decoder stream
|
||||
*
|
||||
* @param _name Name of the stream
|
||||
*/
|
||||
#define DEFAULT_AUDIO_STREAM_CONFIG(_name) { \
|
||||
.type = AUDIO_STREAM_TYPE_DECODER, \
|
||||
.name = _name, \
|
||||
.priority = tskIDLE_PRIORITY + 1, \
|
||||
.coreID = tskNO_AFFINITY \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the current state of a stream
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @return Current audio_player_state_t of the stream
|
||||
*/
|
||||
audio_player_state_t audio_stream_get_state(audio_stream_handle_t h);
|
||||
|
||||
/**
|
||||
* @brief Get the type of a stream
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @return audio_stream_type_t of the stream
|
||||
*/
|
||||
audio_stream_type_t audio_stream_get_type(audio_stream_handle_t h);
|
||||
|
||||
/**
|
||||
* @brief Play an audio file on a stream
|
||||
*
|
||||
* Only supported for DECODER type streams.
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @param fp File pointer to the audio file
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_stream_play(audio_stream_handle_t h, FILE *fp);
|
||||
|
||||
/**
|
||||
* @brief Queue an audio file to be played on a stream
|
||||
*
|
||||
* Only supported for DECODER type streams.
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @param fp File pointer to the audio file
|
||||
* @param play_now If true, start playing immediately (interrupting current playback)
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_stream_queue(audio_stream_handle_t h, FILE *fp, bool play_now);
|
||||
|
||||
/**
|
||||
* @brief Stop playback on a stream
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_stream_stop(audio_stream_handle_t h);
|
||||
|
||||
/**
|
||||
* @brief Pause playback on a stream
|
||||
*
|
||||
* Only supported for DECODER type streams.
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_stream_pause(audio_stream_handle_t h);
|
||||
|
||||
/**
|
||||
* @brief Resume playback on a stream
|
||||
*
|
||||
* Only supported for DECODER type streams.
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a decoder stream
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_stream_resume(audio_stream_handle_t h);
|
||||
|
||||
/**
|
||||
* @brief Direct write raw PCM data to a stream
|
||||
*
|
||||
* Only supported for RAW type streams.
|
||||
* Data format must match the mixer configuration (e.g. 44.1kHz, 16-bit, mono/stereo).
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @param data Pointer to the PCM data
|
||||
* @param size Size of the data in bytes
|
||||
* @param timeout_ms Timeout in milliseconds to wait for space in the stream's buffer
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a raw stream
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_stream_write_pcm(audio_stream_handle_t h, void *data, size_t size, uint32_t timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief Send an event to a raw stream's callback
|
||||
*
|
||||
* Allows manual state management for raw streams.
|
||||
*
|
||||
* @param h Handle of the stream
|
||||
* @param event Event to send
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_NOT_SUPPORTED: Stream is not a raw stream
|
||||
*/
|
||||
esp_err_t audio_stream_raw_send_event(audio_stream_handle_t h, audio_player_callback_event_t event);
|
||||
|
||||
/**
|
||||
* @brief Create a new audio stream
|
||||
*
|
||||
* @param cfg Pointer to the stream configuration structure
|
||||
* @return Handle to the new stream, or NULL if failed
|
||||
*/
|
||||
audio_stream_handle_t audio_stream_new(audio_stream_config_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief Delete an audio stream and free its resources
|
||||
*
|
||||
* @param h Handle of the stream to delete
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - Others: Fail
|
||||
*/
|
||||
esp_err_t audio_stream_delete(audio_stream_handle_t h);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue