Skip to content

Commit 7f87b54

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 166ee16 commit 7f87b54

File tree

7 files changed

+274
-0
lines changed

7 files changed

+274
-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:: samples/subsys/libmp/audio_example/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`.
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: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
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()
28+
{
29+
int gain = 90; /* Set gain to 90% (0.9x amplification) */
30+
int ret = 0;
31+
32+
/* Initialize built-in elements and plugins */
33+
mp_init();
34+
35+
/* Create elements */
36+
MpElement *source = mp_element_factory_create("zaud_dmic_src", "dmic");
37+
if (source == NULL) {
38+
LOG_ERR("Failed to create dmic element");
39+
return 0;
40+
}
41+
42+
MpElement *transform = mp_element_factory_create("zaud_gain", "gain");
43+
if (transform == NULL) {
44+
LOG_ERR("Failed to create gain element");
45+
return 0;
46+
}
47+
48+
MpElement *sink = mp_element_factory_create("zaud_i2s_codec_sink", "speaker");
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+
if (pipeline == NULL) {
77+
LOG_ERR("Failed to create pipeline");
78+
return 0;
79+
}
80+
81+
/* Add elements to the pipeline - order does not matter */
82+
if (mp_bin_add(MP_BIN(pipeline), source, transform, sink, NULL) == false) {
83+
LOG_ERR("Failed to add elements");
84+
return 0;
85+
}
86+
87+
/* Link elements together - order does matter */
88+
if (mp_element_link(source, transform, sink, NULL) == false) {
89+
LOG_ERR("Failed to link elements");
90+
return 0;
91+
}
92+
93+
/* Start playing */
94+
if (mp_element_set_state(pipeline, MP_STATE_PLAYING) != MP_STATE_CHANGE_SUCCESS) {
95+
LOG_ERR("Failed to start pipeline");
96+
return 0;
97+
}
98+
99+
/* Handle message from the pipeline */
100+
MpBus *bus = mp_element_get_bus(pipeline);
101+
/* Wait until an Error or an EOS - blocking */
102+
MpMessage *msg = mp_bus_pop_msg(bus, MP_MESSAGE_ERROR | MP_MESSAGE_EOS);
103+
if (msg != NULL) {
104+
switch (MP_MESSAGE_TYPE(msg)) {
105+
case MP_MESSAGE_ERROR:
106+
LOG_INF("Received ERROR from %s\n", msg->src->name);
107+
break;
108+
case MP_MESSAGE_EOS:
109+
LOG_INF("Received EOS from %s\n", msg->src->name);
110+
break;
111+
default:
112+
LOG_ERR("Unexpected message received from %s\n", msg->src->name);
113+
break;
114+
}
115+
}
116+
117+
/* TODO: Stop the pipeline */
118+
119+
return 0;
120+
}
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)