Skip to content

Commit 55969fa

Browse files
michal-chvatalngphibang
authored andcommitted
lib: libMP: Add zaud plugin
Add plugin for audio which includes source, sink and a gain transform elements. Signed-off-by: Michal Chvatal <[email protected]>
1 parent 9c1da2c commit 55969fa

17 files changed

+1293
-0
lines changed

lib/libmp/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,14 @@ if(CONFIG_MP)
6262
)
6363
endif()
6464

65+
if(CONFIG_MP_PLUGIN_ZAUD)
66+
message("Including zaud plugin")
67+
file(GLOB_RECURSE PLUGIN_ZAUD_SOURCE_FILES ${MP_PLUGIN_DIR}/zaud/*.c)
68+
zephyr_library_sources(
69+
${PLUGIN_ZAUD_SOURCE_FILES}
70+
)
71+
endif()
72+
6573
zephyr_linker_sources(DATA_SECTIONS ${MP_CORE_DIR}/mp.ld)
6674

6775
zephyr_iterable_section(NAME MpElementFactory GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT})

lib/libmp/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ config MP_PLUGIN_ZVID
3636
config MP_PLUGIN_ZDISP
3737
bool "Zdisp plugin support"
3838

39+
config MP_PLUGIN_ZAUD
40+
bool "Zaud plugin support"
41+
3942
endmenu
4043

4144
endif # MP

lib/libmp/mp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,8 @@
3131
#include <src/plugins/zdisp/mp_zdisp_property.h>
3232
#endif
3333

34+
#if CONFIG_MP_PLUGIN_ZAUD
35+
#include <src/plugins/zaud/mp_zaud_property.h>
36+
#endif
37+
3438
#endif /* __MP_H__ */

lib/libmp/src/core/mp_plugin.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ enum mp_element_factory_id {
3636
/* Display plugin elements */
3737
/** Display sink */
3838
MP_ZDISP_SINK_ELEM,
39+
/* Audio plugin elements */
40+
/** DMIC source */
41+
MP_ZAUD_DMIC_SRC_ELEM,
42+
/** DMIC gain */
43+
MP_ZAUD_GAIN_ELEM,
44+
/** I2S codec sink */
45+
MP_ZAUD_I2S_CODEC_SINK_ELEM,
3946
/** Last item for counter only */
4047
MP_ELEM_COUNT,
4148
};
@@ -49,6 +56,8 @@ enum mp_plugin_id {
4956
MP_ZVID_PLUGIN = 0,
5057
/** Display plugin */
5158
MP_ZDISP_PLUGIN,
59+
/** Audio plugin */
60+
MP_ZAUD_PLUGIN,
5261
/** Last item for counter only */
5362
MP_PLUGIN_COUNT,
5463
};
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/audio/audio_caps.h>
8+
9+
#include <src/core/mp_element_factory.h>
10+
#include <src/core/mp_plugin.h>
11+
12+
#include "mp_zaud.h"
13+
#include "mp_zaud_dmic_src.h"
14+
#include "mp_zaud_gain.h"
15+
#include "mp_zaud_i2s_codec_sink.h"
16+
17+
struct mp_zaud_desc {
18+
uint32_t value;
19+
uint32_t mask;
20+
};
21+
22+
static const struct mp_zaud_desc mp_zaud_sample_rates[] = {
23+
{MP_ZAUD_SAMPLE_RATE_8000, AUDIO_SAMPLE_RATE_8000},
24+
{MP_ZAUD_SAMPLE_RATE_16000, AUDIO_SAMPLE_RATE_16000},
25+
{MP_ZAUD_SAMPLE_RATE_32000, AUDIO_SAMPLE_RATE_32000},
26+
{MP_ZAUD_SAMPLE_RATE_44100, AUDIO_SAMPLE_RATE_44100},
27+
{MP_ZAUD_SAMPLE_RATE_48000, AUDIO_SAMPLE_RATE_48000},
28+
{MP_ZAUD_SAMPLE_RATE_96000, AUDIO_SAMPLE_RATE_96000},
29+
};
30+
31+
static const struct mp_zaud_desc mp_zaud_bit_widths[] = {
32+
{MP_ZAUD_BIT_WIDTH_16, AUDIO_BIT_WIDTH_16},
33+
{MP_ZAUD_BIT_WIDTH_24, AUDIO_BIT_WIDTH_24},
34+
{MP_ZAUD_BIT_WIDTH_32, AUDIO_BIT_WIDTH_32},
35+
};
36+
37+
const uint32_t audio2mp_sample_rate(uint32_t sample_rate_mask)
38+
{
39+
for (uint8_t i = 0; i < ARRAY_SIZE(mp_zaud_sample_rates); i++) {
40+
if (mp_zaud_sample_rates[i].mask == sample_rate_mask) {
41+
return mp_zaud_sample_rates[i].value;
42+
}
43+
}
44+
45+
return 0;
46+
}
47+
48+
const uint32_t audio2mp_bit_width(uint32_t bit_width_mask)
49+
{
50+
for (uint8_t i = 0; i < ARRAY_SIZE(mp_zaud_bit_widths); i++) {
51+
if (mp_zaud_bit_widths[i].mask == bit_width_mask) {
52+
return mp_zaud_bit_widths[i].value;
53+
}
54+
}
55+
56+
return 0;
57+
}
58+
59+
static void plugin_init(void)
60+
{
61+
MP_ELEMENT_FACTORY_DEFINE(MP_ZAUD_DMIC_SRC_ELEM, sizeof(struct mp_zaud_dmic_src),
62+
mp_zaud_dmic_src_init);
63+
MP_ELEMENT_FACTORY_DEFINE(MP_ZAUD_GAIN_ELEM, sizeof(struct mp_zaud_gain),
64+
mp_zaud_gain_init);
65+
MP_ELEMENT_FACTORY_DEFINE(MP_ZAUD_I2S_CODEC_SINK_ELEM,
66+
sizeof(struct mp_zaud_i2s_codec_sink),
67+
mp_zaud_i2s_codec_sink_init);
68+
}
69+
70+
MP_PLUGIN_DEFINE(MP_ZAUD_PLUGIN, plugin_init);
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief Audio definitions and utilities header file.
10+
*/
11+
12+
#ifndef __MP_ZAUD_H__
13+
#define __MP_ZAUD_H__
14+
15+
#include <zephyr/audio/audio_caps.h>
16+
17+
/**
18+
* @brief Supported MediaPipe sample rates (Hz)
19+
* @{
20+
*/
21+
/** @brief 8 kHz sample rate */
22+
#define MP_ZAUD_SAMPLE_RATE_8000 8000
23+
/** @brief 16 kHz sample rate */
24+
#define MP_ZAUD_SAMPLE_RATE_16000 16000
25+
/** @brief 32 kHz sample rate */
26+
#define MP_ZAUD_SAMPLE_RATE_32000 32000
27+
/** @brief 44.1 kHz sample rate */
28+
#define MP_ZAUD_SAMPLE_RATE_44100 44100
29+
/** @brief 48 kHz sample rate */
30+
#define MP_ZAUD_SAMPLE_RATE_48000 48000
31+
/** @brief 96 kHz sample rate */
32+
#define MP_ZAUD_SAMPLE_RATE_96000 96000
33+
/** @} */
34+
35+
/**
36+
* @brief Supported MediaPipe bit widths
37+
* @{
38+
*/
39+
/** @brief 16 bit width */
40+
#define MP_ZAUD_BIT_WIDTH_16 16
41+
/** @brief 24 bit width */
42+
#define MP_ZAUD_BIT_WIDTH_24 24
43+
/** @brief 32 bit width */
44+
#define MP_ZAUD_BIT_WIDTH_32 32
45+
/** @} */
46+
47+
/**
48+
* @brief Convert audio sample rate mask to MediaPipe sample rate
49+
*
50+
* @param sample_rate_mask Audio driver sample rate mask
51+
* @return Corresponding MediaPipe sample rate value
52+
*/
53+
const uint32_t audio2mp_sample_rate(uint32_t sample_rate_mask);
54+
55+
/**
56+
* @brief Convert audio bit width mask to MediaPipe bit width
57+
*
58+
* @param bit_width_mask Audio driver bit width mask
59+
* @return Corresponding MediaPipe bit width value
60+
*/
61+
const uint32_t audio2mp_bit_width(uint32_t bit_width_mask);
62+
63+
#endif /* __MP_ZAUD_H__ */
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/logging/log.h>
8+
9+
#include "mp_zaud.h"
10+
#include "mp_zaud_buffer_pool.h"
11+
12+
LOG_MODULE_REGISTER(mp_zaud_buffer_pool, CONFIG_LIBMP_LOG_LEVEL);
13+
14+
static bool mp_zaud_buffer_pool_config(struct mp_buffer_pool *pool, struct mp_structure *config)
15+
{
16+
struct mp_zaud_buffer_pool *zaud_pool = MP_ZAUD_BUFFER_POOL(pool);
17+
void *aligned_buffer = NULL;
18+
19+
int sample_rate = mp_value_get_int(mp_structure_get_value(config, "samplerate"));
20+
int bit_width = mp_value_get_int(mp_structure_get_value(config, "bitwidth"));
21+
int num_of_channel = mp_value_get_int(mp_structure_get_value(config, "numOfchannel"));
22+
uint32_t frame_interval =
23+
mp_value_get_uint(mp_structure_get_value(config, "frameinterval"));
24+
int buffer_count = mp_value_get_int(mp_structure_get_value(config, "buffercount"));
25+
26+
/*
27+
* TEMPORARY WORKAROUND: Adding 2 extra buffers to the minimum count
28+
*
29+
* Currently adding +2 buffers beyond the requested buffer_count because
30+
* the current buffer management system requires additional buffers
31+
*
32+
* This is a temporary solution
33+
*
34+
* TODO: Remove this hardcoded +2 offset when:
35+
* - Buffer lifecycle management is properly implemented
36+
* - Proper flow control prevents buffer starvation
37+
*/
38+
pool->config.min_buffers = buffer_count + 2;
39+
pool->config.size = (bit_width / BITS_PER_BYTE) * (sample_rate * frame_interval / 1000000) *
40+
num_of_channel;
41+
/* The address needs to be aligned to the size of the DMA transfer */
42+
pool->config.align = bit_width >> 3;
43+
44+
/* Allocate just the pool's buffers structure */
45+
pool->buffers = k_calloc(pool->config.min_buffers, sizeof(struct mp_buffer));
46+
if (pool->buffers == NULL) {
47+
LOG_ERR("Unable to allocate pool buffer");
48+
return false;
49+
}
50+
51+
/* TODO: Need to allocate in non-cachable memory */
52+
zaud_pool->unaligned_buffer = (void *)k_calloc(
53+
1, (pool->config.size * pool->config.min_buffers) + (pool->config.align - 1));
54+
if (zaud_pool->unaligned_buffer == NULL) {
55+
LOG_ERR("Unable to allocate mem_slab buffer");
56+
return false;
57+
}
58+
59+
/* Align buffer to required alignment */
60+
uintptr_t unaligned_addr = (uintptr_t)zaud_pool->unaligned_buffer;
61+
uintptr_t aligned_addr =
62+
(unaligned_addr + pool->config.align - 1) & ~(pool->config.align - 1);
63+
aligned_buffer = (void *)aligned_addr;
64+
65+
k_mem_slab_init(zaud_pool->mem_slab, aligned_buffer, pool->config.size,
66+
pool->config.min_buffers);
67+
68+
for (uint8_t i = 0; i < pool->config.min_buffers; i++) {
69+
/* Wrap mem_slab buffer to generic libMP buffer */
70+
pool->buffers[i].pool = pool;
71+
pool->buffers[i].size = pool->config.size;
72+
pool->buffers[i].data = &(zaud_pool->mem_slab->buffer[pool->config.size * i]);
73+
pool->buffers[i].index = i;
74+
}
75+
76+
return true;
77+
}
78+
79+
static bool mp_zaud_buffer_pool_stop(struct mp_buffer_pool *pool)
80+
{
81+
struct mp_zaud_buffer_pool *zaud_pool = MP_ZAUD_BUFFER_POOL(pool);
82+
83+
if (pool->buffers != NULL) {
84+
k_free(pool->buffers);
85+
pool->buffers = NULL;
86+
}
87+
88+
if (zaud_pool->mem_slab->buffer != NULL) {
89+
k_free(zaud_pool->unaligned_buffer);
90+
zaud_pool->unaligned_buffer = NULL;
91+
zaud_pool->mem_slab->buffer = NULL;
92+
}
93+
94+
zaud_pool->mem_slab = NULL;
95+
96+
return true;
97+
}
98+
99+
void mp_zaud_buffer_pool_init(struct mp_buffer_pool *pool)
100+
{
101+
struct mp_zaud_buffer_pool *zaud_pool = MP_ZAUD_BUFFER_POOL(pool);
102+
103+
zaud_pool->zaud_dev = NULL;
104+
zaud_pool->mem_slab = NULL;
105+
106+
mp_buffer_pool_init(pool);
107+
108+
pool->configure = mp_zaud_buffer_pool_config;
109+
pool->stop = mp_zaud_buffer_pool_stop;
110+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* @file
9+
* @brief Audio buffer pool header file.
10+
*/
11+
12+
#ifndef __MP_ZAUD_BUFFER_POOL_H__
13+
#define __MP_ZAUD_BUFFER_POOL_H__
14+
15+
#include <zephyr/device.h>
16+
17+
#include <src/core/mp_buffer.h>
18+
19+
#include "mp_zaud.h"
20+
21+
/** @brief Cast object pointer to mp_zaud_buffer_pool pointer */
22+
#define MP_ZAUD_BUFFER_POOL(self) ((struct mp_zaud_buffer_pool *)self)
23+
24+
/**
25+
* @struct mp_zaud_buffer_pool
26+
* @brief Audio buffer pool structure
27+
*
28+
* This structure manages memory allocation and buffer handling for audio
29+
* data processing within the plugin.
30+
*/
31+
struct mp_zaud_buffer_pool {
32+
/** Base buffer pool structure */
33+
struct mp_buffer_pool pool;
34+
/** Pointer to the associated audio device */
35+
const struct device *zaud_dev;
36+
/** Memory slab for efficient buffer allocation */
37+
struct k_mem_slab *mem_slab;
38+
/** Pointer to unaligned buffer memory */
39+
void *unaligned_buffer;
40+
};
41+
42+
/**
43+
* @brief Initialize an audio buffer pool
44+
*
45+
* This function initializes the audio buffer pool with default
46+
* values and sets up the function pointers.
47+
*
48+
* @param pool Pointer to the buffer pool structure to initialize.
49+
*/
50+
void mp_zaud_buffer_pool_init(struct mp_buffer_pool *pool);
51+
52+
#endif /* __MP_ZAUD_BUFFER_POOL_H__ */

0 commit comments

Comments
 (0)