Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@

set(srcs
"audio_player.cpp"
"audio_mixer.cpp"
)

set(includes
"include"
)

set(requires "")
set(requires)

if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER_EQUAL "5.3")
list(APPEND requires esp_driver_i2s esp_ringbuf)
else()
list(APPEND requires driver)
endif()

if(CONFIG_AUDIO_PLAYER_ENABLE_MP3)
list(APPEND srcs "audio_mp3.cpp")
Expand All @@ -21,7 +28,6 @@ if(CONFIG_AUDIO_PLAYER_ENABLE_WAV)
endif()

idf_component_register(SRCS "${srcs}"
REQUIRES "${requires}"
INCLUDE_DIRS "${includes}"
REQUIRES driver
REQUIRES "${requires}"
)
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

* MP3 decoding (via libhelix-mp3)
* Wav/wave file decoding
* Audio mixing (multiple concurrent streams)

## Who is this for?

Expand Down Expand Up @@ -49,6 +50,40 @@ For MP3 support you'll need the [esp-libhelix-mp3](https://github.com/chmorgan/e

Unity tests are implemented in the [test/](../test) folder.


## Audio Mixer

The Audio Mixer allows for concurrent playback of multiple audio streams. It supports two types of streams:

* **Decoder Streams**: For playing MP3 or WAV files. Each stream runs its own decoding task.
* **Raw PCM Streams**: For writing raw PCM data directly to the mixer.

### Basic Mixer Usage

1. Initialize the mixer with output format and I2S write functions.
2. Create one or more streams using `audio_stream_new()`.
3. Start playback on the streams.

```c
audio_mixer_config_t mixer_cfg = {
.write_fn = bsp_i2s_write,
.clk_set_fn = bsp_i2s_reconfig_clk,
.i2s_format = {
.sample_rate = 44100,
.bits_per_sample = 16,
.channels = 2
},
// ...
};
audio_mixer_init(&mixer_cfg);

audio_stream_config_t stream_cfg = DEFAULT_AUDIO_STREAM_CONFIG("bgm");
audio_stream_handle_t bgm_stream = audio_stream_new(&stream_cfg);

FILE *f = fopen("/sdcard/music.mp3", "rb");
audio_stream_play(bgm_stream, f);
```

## States

```mermaid
Expand Down
35 changes: 35 additions & 0 deletions audio_instance.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#pragma once

#include "esp_err.h"
#include "include/audio_player.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
* Opaque handle for a player instance.
* Used for multi-instance control in mixer
*/
typedef void* audio_instance_handle_t;

#define CHECK_INSTANCE(i) \
ESP_RETURN_ON_FALSE(i != NULL, ESP_ERR_INVALID_ARG, "audio_instance", "instance is NULL")

const char* event_to_string(audio_player_callback_event_t event);
audio_player_callback_event_t state_to_event(audio_player_state_t state);

audio_player_state_t audio_instance_get_state(audio_instance_handle_t h);
esp_err_t audio_instance_callback_register(audio_instance_handle_t h, audio_player_cb_t call_back, void *user_ctx);

esp_err_t audio_instance_play(audio_instance_handle_t h, FILE *fp);
esp_err_t audio_instance_pause(audio_instance_handle_t h);
esp_err_t audio_instance_resume(audio_instance_handle_t h);
esp_err_t audio_instance_stop(audio_instance_handle_t h);

esp_err_t audio_instance_new(audio_instance_handle_t *h, audio_player_config_t *config);
esp_err_t audio_instance_delete(audio_instance_handle_t h);

#ifdef __cplusplus
}
#endif
Loading