Skip to content

Commit 8660dcc

Browse files
michal-chvatalngphibang
authored andcommitted
samples: subsys: libMP: Add audio example
Add example for audio with a pipeline consists of a dmic source, a gain transform and a i2s sink element. Signed-off-by: Michal Chvatal <[email protected]>
1 parent 2309fd8 commit 8660dcc

File tree

7 files changed

+276
-0
lines changed

7 files changed

+276
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CMAKE_MINIMUM_REQUIRED (VERSION 3.20.0)
2+
3+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
4+
5+
project(audio_example)
6+
7+
target_sources(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dmic_gain_speaker.c)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright 2024-2025 NXP
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
source "Kconfig.zephyr"
5+
6+
config CODEC_MASTER
7+
bool "Configure the selected codec device as a master device."
8+
default true
9+
10+
config I2S_MASTER
11+
bool "Configure the selected I2S peripheral as a master device."
12+
default false
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
.. zephyr:code-sample:: libmp_dmic_gain_speaker
2+
:name: DMIC-Gain-Speaker Audio Pipeline
3+
4+
Overview
5+
********
6+
7+
This sample demonstrates audio processing. It creates a simple audio pipeline
8+
that captures audio from a digital microphone (DMIC), applies gain control, and
9+
outputs the processed audio through an I2S codec to a speaker.
10+
11+
The sample showcases:
12+
13+
* Digital microphone audio capture
14+
* Real-time audio gain processing
15+
* I2S codec audio output
16+
* Media pipeline creation and management
17+
18+
Requirements
19+
************
20+
21+
* A board with digital microphone (DMIC) support
22+
* A board with I2S support
23+
* Sufficient RAM for audio buffering
24+
* DMA support for audio operations
25+
26+
This sample has been tested on mimxrt685_evk/mimxrt685s/cm33
27+
28+
Building and Running
29+
********************
30+
31+
This sample can be found under :zephyr_file:`samples/subsys/libmp/audio_example/dmic_gain_speaker.c`.
32+
33+
For :zephyr:board:`mimxrt685_evk`, build this sample application with the following commands:
34+
35+
.. zephyr-app-commands::
36+
:zephyr-app: samples/subsys/libmp/audio_example
37+
:board: mimxrt685_evk/mimxrt685s/cm33
38+
:goals: build flash
39+
:compact:
40+
41+
Connect headphones or speakers to the audio output to hear the processed
42+
audio from the DMIC.
43+
44+
Sample Output
45+
*************
46+
47+
The application will start the audio pipeline and process audio in real-time.
48+
Check for any error messages during initialization:
49+
50+
.. code-block:: console
51+
52+
*** Booting Zephyr OS build ***
53+
[00:01:56.811,938] <inf> wolfson_wm8904: blk 512000
54+
[00:01:57.816,263] <inf> mp_zaud_dmic_src: Capture started
55+
56+
Configuration Options
57+
*********************
58+
59+
The sample supports the following configuration options:
60+
61+
* **Gain Level**: Adjustable audio gain (0-1000 %), default is 90 %
62+
63+
Devicetree Configuration
64+
************************
65+
66+
The sample requires proper devicetree configuration for:
67+
68+
* ``dmic_dev`` node label for dmic.
69+
* ``i2s_codec_tx`` node alias for i2s.
70+
* ``audio_codec`` node label for audio codec.
71+
72+
Implementation Details
73+
**********************
74+
75+
The sample creates a three-element pipeline:
76+
77+
1. **DMIC Source** (``zaud_dmic_src``): Captures audio from digital microphone
78+
2. **Gain Transform** (``zaud_gain``): Applies configurable gain to audio signal
79+
3. **I2S Codec Sink** (``zaud_i2s_codec_sink``): Outputs processed audio
80+
81+
The pipeline uses DMA-compatible memory slabs for efficient audio buffer management.
82+
The ``__nocache`` attribute ensures proper DMA operation by preventing cache
83+
coherency issues.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#
2+
# Copyright 2025 NXP
3+
#
4+
# SPDX-License-Identifier: Apache-2.0
5+
#
6+
7+
CONFIG_I3C=y
8+
CONFIG_AUDIO=y
9+
CONFIG_AUDIO_CODEC=y
10+
CONFIG_CODEC_MASTER=y
11+
CONFIG_I2S_MASTER=n
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
aliases {
9+
i2s-codec-rx = &i2s0;
10+
i2s-codec-tx = &i2s1;
11+
};
12+
};
13+
14+
&i3c0 {
15+
status = "okay";
16+
};
17+
18+
&i2s0 {
19+
status = "okay";
20+
};
21+
22+
&i2s1 {
23+
status = "okay";
24+
};
25+
26+
dmic_dev: &dmic0 {
27+
status = "okay";
28+
};
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright 2025 NXP
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <zephyr/kernel.h>
8+
#include <zephyr/logging/log.h>
9+
10+
#include <mp.h>
11+
12+
LOG_MODULE_REGISTER(main);
13+
14+
#define LOG_LEVEL LOG_LEVEL_DBG
15+
16+
/*
17+
* WORKAROUND: Direct memory slab management in application code
18+
*
19+
* TODO: Normally, applications should not set this because they do not
20+
* need to know about the memory slab audio buffers implementation.
21+
*
22+
* The __nocache attribute ensures this memory is not cached, which is
23+
* required for DMA operations used by audio hardware.
24+
*/
25+
__nocache struct k_mem_slab mem_slab;
26+
27+
int main(void)
28+
{
29+
int gain = 90; /* Set gain to 90% (0.9x amplification) */
30+
int ret = 0;
31+
32+
/* Create elements */
33+
MpElement *source = mp_element_factory_create("zaud_dmic_src", "dmic");
34+
35+
if (source == NULL) {
36+
LOG_ERR("Failed to create dmic element");
37+
return 0;
38+
}
39+
40+
MpElement *transform = mp_element_factory_create("zaud_gain", "gain");
41+
42+
if (transform == NULL) {
43+
LOG_ERR("Failed to create gain element");
44+
return 0;
45+
}
46+
47+
MpElement *sink = mp_element_factory_create("zaud_i2s_codec_sink", "speaker");
48+
49+
if (sink == NULL) {
50+
LOG_ERR("Failed to create speaker element");
51+
return 0;
52+
}
53+
54+
ret = mp_object_set_properties(MP_OBJECT(source), PROP_ZAUD_SRC_SLAB_PTR, &mem_slab,
55+
PROP_LIST_END);
56+
if (ret < 0) {
57+
LOG_ERR("Failed to set properties for dmic element");
58+
return 0;
59+
}
60+
61+
ret = mp_object_set_properties(MP_OBJECT(transform), PROP_GAIN, &gain, PROP_LIST_END);
62+
if (ret < 0) {
63+
LOG_ERR("Failed to set properties for transform element");
64+
return 0;
65+
}
66+
67+
ret = mp_object_set_properties(MP_OBJECT(sink), PROP_ZAUD_SINK_SLAB_PTR, &mem_slab,
68+
PROP_LIST_END);
69+
if (ret < 0) {
70+
LOG_ERR("Failed to set properties for speaker element");
71+
return 0;
72+
}
73+
74+
/* Create a new pipeline */
75+
MpElement *pipeline = mp_pipeline_new("dmic_gain_speaker_pipeline");
76+
77+
if (pipeline == NULL) {
78+
LOG_ERR("Failed to create pipeline");
79+
return 0;
80+
}
81+
82+
/* Add elements to the pipeline - order does not matter */
83+
if (mp_bin_add(MP_BIN(pipeline), source, transform, sink, NULL) == false) {
84+
LOG_ERR("Failed to add elements");
85+
return 0;
86+
}
87+
88+
/* Link elements together - order does matter */
89+
if (mp_element_link(source, transform, sink, NULL) == false) {
90+
LOG_ERR("Failed to link elements");
91+
return 0;
92+
}
93+
94+
/* Start playing */
95+
if (mp_element_set_state(pipeline, MP_STATE_PLAYING) != MP_STATE_CHANGE_SUCCESS) {
96+
LOG_ERR("Failed to start pipeline");
97+
return 0;
98+
}
99+
100+
/* Handle message from the pipeline */
101+
MpBus *bus = mp_element_get_bus(pipeline);
102+
/* Wait until an Error or an EOS - blocking */
103+
MpMessage *msg = mp_bus_pop_msg(bus, MP_MESSAGE_ERROR | MP_MESSAGE_EOS);
104+
105+
if (msg != NULL) {
106+
switch (MP_MESSAGE_TYPE(msg)) {
107+
case MP_MESSAGE_ERROR:
108+
LOG_INF("Received ERROR from %s\n", msg->src->name);
109+
break;
110+
case MP_MESSAGE_EOS:
111+
LOG_INF("Received EOS from %s\n", msg->src->name);
112+
break;
113+
default:
114+
LOG_ERR("Unexpected message received from %s\n", msg->src->name);
115+
break;
116+
}
117+
}
118+
119+
/* TODO: Stop the pipeline */
120+
121+
return 0;
122+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
CONFIG_LOG=y
2+
CONFIG_HEAP_MEM_POOL_SIZE=20000
3+
4+
CONFIG_MP=y
5+
CONFIG_MP_PLUGIN_ZAUD=y
6+
7+
CONFIG_I2S=y
8+
CONFIG_AUDIO=y
9+
CONFIG_AUDIO_DMIC=y
10+
CONFIG_AUDIO_CODEC=y
11+
12+
CONFIG_SHELL=y
13+
CONFIG_DEVICE_SHELL=y

0 commit comments

Comments
 (0)