Skip to content

Commit

Permalink
Add all esp adf decoders
Browse files Browse the repository at this point in the history
Signed-off-by: Paul Guyot <pguyot@kallisys.net>
  • Loading branch information
pguyot committed May 13, 2024
1 parent c8d3afc commit 4e75341
Show file tree
Hide file tree
Showing 26 changed files with 1,202 additions and 132 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,24 @@ jobs:
idf-version:
- 'v5.1.3'
- 'v5.2.1'
additional_opts: [""]

include:
- additional_opts: "FLAC_DECODER OGG_DECODER"
soc: "esp32c3"
idf-version: "v5.2.1"

- additional_opts: "G711_DECODER OPUS_DECODER"
soc: "esp32c3"
idf-version: "v5.2.1"

- additional_opts: "AMR_DECODER"
soc: "esp32c3"
idf-version: "v5.2.1"

- additional_opts: "PCM_DECODER WAV_DECODER"
soc: "esp32c3"
idf-version: "v5.2.1"

container: espressif/idf:${{ matrix.idf-version }}
steps:
Expand Down Expand Up @@ -65,6 +83,9 @@ jobs:
. $IDF_PATH/export.sh
idf.py set-target ${{ matrix.soc }}
echo CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y >> sdkconfig
for codec in "${{ matrix.additional_opts }}" ; do
echo AVM_ESP_ADF_${codec}_ENABLE=y >> sdkconfig
done
idf.py build -DCONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y
- name: Run tests using qemu
Expand Down
10 changes: 9 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,20 @@
#

set(ATOMVM_ESP_AUDIO_COMPONENT_SRCS
"nifs/atomvm_esp_adf_aac_decoder.c"
"nifs/atomvm_esp_adf_amr_decoder.c"
"nifs/atomvm_esp_adf_audio_element.c"
"nifs/atomvm_esp_adf_audio_pipeline.c"
"nifs/atomvm_esp_adf_aac_decoder.c"
"nifs/atomvm_esp_adf_common.c"
"nifs/atomvm_esp_adf_flac_decoder.c"
"nifs/atomvm_esp_adf_g711_decoder.c"
"nifs/atomvm_esp_adf_i2s_output.c"
"nifs/atomvm_esp_adf_mp3_decoder.c"
"nifs/atomvm_esp_adf_ogg_decoder.c"
"nifs/atomvm_esp_adf_opus_decoder.c"
"nifs/atomvm_esp_adf_pcm_decoder.c"
"nifs/atomvm_esp_adf_rsp_filter.c"
"nifs/atomvm_esp_adf_wav_decoder.c"
)

# WHOLE_ARCHIVE option is supported only with esp-idf 5.x
Expand Down
35 changes: 35 additions & 0 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,46 @@ config AVM_ESP_ADF_AAC_DECODER_ENABLE
default y
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_AMR_DECODER_ENABLE
bool "Enable AtomVM esp adf amr decoder"
default n
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_FLAC_DECODER_ENABLE
bool "Enable AtomVM esp adf flac decoder"
default n
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_G711_DECODER_ENABLE
bool "Enable AtomVM esp adf g711 decoder"
default n
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_MP3_DECODER_ENABLE
bool "Enable AtomVM esp adf mp3 decoder"
default y
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_OGG_DECODER_ENABLE
bool "Enable AtomVM esp adf ogg decoder"
default n
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_OPUS_DECODER_ENABLE
bool "Enable AtomVM esp adf opus decoder"
default n
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_PCM_DECODER_ENABLE
bool "Enable AtomVM esp adf pcm decoder"
default n
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_WAV_DECODER_ENABLE
bool "Enable AtomVM esp adf wav decoder"
default n
depends on AVM_ESP_ADF_AUDIO_ELEMENT_ENABLE

config AVM_ESP_ADF_RSP_FILTER_ENABLE
bool "Enable AtomVM esp adf rsp filter"
default y
Expand Down
20 changes: 19 additions & 1 deletion nifs/atomvm_esp_adf_aac_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <term.h>

#include "atomvm_esp_adf_audio_element.h"
#include "atomvm_esp_adf_common.h"

// #define ENABLE_TRACE
#include <trace.h>
Expand Down Expand Up @@ -55,10 +56,27 @@ static term nif_init(Context *ctx, int argc, term argv[])
}

aac_decoder_cfg_t aac_cfg = DEFAULT_AAC_DECODER_CONFIG();
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\xB", "out_rb_size"), &aac_cfg.out_rb_size, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\xA", "task_stack"), &aac_cfg.task_stack, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\x9", "task_core"), &aac_cfg.task_core, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\x9", "task_prio"), &aac_cfg.task_prio, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_bool_parameter(ctx, argv, ATOM_STR("\xC", "stack_in_ext"), &aac_cfg.stack_in_ext))) {
return term_invalid_term();
}
if (UNLIKELY(!get_bool_parameter(ctx, argv, ATOM_STR("\xB", "plus_enable"), &aac_cfg.plus_enable))) {
return term_invalid_term();
}
audio_element_handle_t audio_element = aac_decoder_init(&aac_cfg);

atomvm_esp_adf_audio_element_init_resource(rsrc_obj, audio_element, active_term == TRUE_ATOM, ctx);

return atomvm_esp_adf_audio_element_resource_to_opaque(rsrc_obj, ctx);
}

Expand Down
102 changes: 102 additions & 0 deletions nifs/atomvm_esp_adf_amr_decoder.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/* SPDX-License-Identifier: MIT */
#include <sdkconfig.h>

#ifdef CONFIG_AVM_ESP_ADF_AMR_DECODER_ENABLE

#include <stdlib.h>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpedantic"

#include <esp_attr.h>
#include <esp_log.h>
#include <esp_system.h>

#include <amr_decoder.h>

#pragma GCC diagnostic pop

#include <context.h>
#include <defaultatoms.h>
#include <erl_nif.h>
#include <erl_nif_priv.h>
#include <esp32_sys.h>
#include <interop.h>
#include <memory.h>
#include <nifs.h>
#include <resources.h>
#include <term.h>

#include "atomvm_esp_adf_audio_element.h"
#include "atomvm_esp_adf_common.h"

// #define ENABLE_TRACE
#include <trace.h>

#define MODULE_PREFIX "esp_adf_amr_decoder:"
#define TAG "esp_adf_amr_decoder"

static term nif_init(Context *ctx, int argc, term argv[])
{
TRACE("%s\n", __func__);
UNUSED(argc);

VALIDATE_VALUE(argv[0], term_is_list);
term active_term = interop_kv_get_value_default(argv[0], ATOM_STR("\x6", "active"), TRUE_ATOM, ctx->global);

if (UNLIKELY(memory_ensure_free(ctx, AUDIO_ELEMENT_OPAQUE_TERM_SIZE) != MEMORY_GC_OK)) {
ESP_LOGW(TAG, "Failed to allocate memory: %s:%i.", __FILE__, __LINE__);
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}

struct AudioElementResource *rsrc_obj = enif_alloc_resource(audio_element_resource_type, sizeof(struct AudioElementResource));
if (IS_NULL_PTR(rsrc_obj)) {
ESP_LOGW(TAG, "Failed to allocate memory: %s:%i.\n", __FILE__, __LINE__);
RAISE_ERROR(OUT_OF_MEMORY_ATOM);
}

amr_decoder_cfg_t amr_cfg = DEFAULT_AMR_DECODER_CONFIG();
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\xB", "out_rb_size"), &amr_cfg.out_rb_size, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\xA", "task_stack"), &amr_cfg.task_stack, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\x9", "task_core"), &amr_cfg.task_core, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_integer_parameter(ctx, argv, ATOM_STR("\x9", "task_prio"), &amr_cfg.task_prio, false))) {
return term_invalid_term();
}
if (UNLIKELY(!get_bool_parameter(ctx, argv, ATOM_STR("\xC", "stack_in_ext"), &amr_cfg.stack_in_ext))) {
return term_invalid_term();
}
audio_element_handle_t audio_element = amr_decoder_init(&amr_cfg);

atomvm_esp_adf_audio_element_init_resource(rsrc_obj, audio_element, active_term == TRUE_ATOM, ctx);
return atomvm_esp_adf_audio_element_resource_to_opaque(rsrc_obj, ctx);
}

static const struct Nif init_nif = {
.base.type = NIFFunctionType,
.nif_ptr = nif_init
};

//
// Component Nif Entrypoints
//

static const struct Nif *get_nif(const char *nifname)
{
if (memcmp(nifname, MODULE_PREFIX, strlen(MODULE_PREFIX))) {
return NULL;
}
if (strcmp(nifname + strlen(MODULE_PREFIX), "init/1") == 0) {
return &init_nif;
}
return NULL;
}

REGISTER_NIF_COLLECTION(esp_adf_amr_decoder, NULL, NULL, get_nif)

#endif
62 changes: 62 additions & 0 deletions nifs/atomvm_esp_adf_common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/* SPDX-License-Identifier: MIT */
#include <sdkconfig.h>

#include <stdbool.h>

#include <context.h>
#include <defaultatoms.h>
#include <interop.h>
#include <nifs.h>
#include <term.h>

#include "atomvm_esp_adf_common.h"

bool get_integer_parameter(Context *ctx, term argv[], AtomString key, int *value, bool required)
{
term parameter_term = interop_kv_get_value(argv[0], key, ctx->global);
if (term_is_invalid_term(parameter_term)) {
if (required) {
RAISE_ERROR(BADARG_ATOM);
return false;
}
return true;
}
if (UNLIKELY(!term_is_integer(parameter_term))) {
RAISE_ERROR(BADARG_ATOM);
return false;
}
*value = term_to_int(parameter_term);
return true;
}

bool get_bool_parameter(Context *ctx, term argv[], AtomString key, bool *value)
{
term parameter_term = interop_kv_get_value(argv[0], key, ctx->global);
if (term_is_invalid_term(parameter_term)) {
return true;
}
if (UNLIKELY(!term_is_atom(parameter_term) || (parameter_term != TRUE_ATOM && parameter_term != FALSE_ATOM))) {
RAISE_ERROR(BADARG_ATOM);
return false;
}
*value = parameter_term == TRUE_ATOM;
return true;
}

bool get_enum_parameter(Context *ctx, term argv[], AtomString key, const AtomStringIntPair *table, int *value)
{
term parameter_term = interop_kv_get_value(argv[0], key, ctx->global);
if (term_is_invalid_term(parameter_term)) {
return true;
}
if (UNLIKELY(!term_is_atom(parameter_term))) {
RAISE_ERROR(BADARG_ATOM);
return false;
}
int enum_value = interop_atom_term_select_int(table, parameter_term, ctx->global);
if (enum_value < 0) {
return false;
}
*value = enum_value;
return true;
}
Loading

0 comments on commit 4e75341

Please sign in to comment.