Skip to content

Commit 3018f17

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 7bade39 commit 3018f17

File tree

7 files changed

+271
-0
lines changed

7 files changed

+271
-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: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
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+
/* Create elements */
33+
MpElement *source = mp_element_factory_create("zaud_dmic_src", "dmic");
34+
if (source == NULL) {
35+
LOG_ERR("Failed to create dmic element");
36+
return 0;
37+
}
38+
39+
MpElement *transform = mp_element_factory_create("zaud_gain", "gain");
40+
if (transform == NULL) {
41+
LOG_ERR("Failed to create gain element");
42+
return 0;
43+
}
44+
45+
MpElement *sink = mp_element_factory_create("zaud_i2s_codec_sink", "speaker");
46+
if (sink == NULL) {
47+
LOG_ERR("Failed to create speaker element");
48+
return 0;
49+
}
50+
51+
ret = mp_object_set_properties(MP_OBJECT(source), PROP_ZAUD_SRC_SLAB_PTR, &mem_slab,
52+
PROP_LIST_END);
53+
if (ret < 0) {
54+
LOG_ERR("Failed to set properties for dmic element");
55+
return 0;
56+
}
57+
58+
ret = mp_object_set_properties(MP_OBJECT(transform), PROP_GAIN, &gain, PROP_LIST_END);
59+
if (ret < 0) {
60+
LOG_ERR("Failed to set properties for transform element");
61+
return 0;
62+
}
63+
64+
ret = mp_object_set_properties(MP_OBJECT(sink), PROP_ZAUD_SINK_SLAB_PTR, &mem_slab,
65+
PROP_LIST_END);
66+
if (ret < 0) {
67+
LOG_ERR("Failed to set properties for speaker element");
68+
return 0;
69+
}
70+
71+
/* Create a new pipeline */
72+
MpElement *pipeline = mp_pipeline_new("dmic_gain_speaker_pipeline");
73+
if (pipeline == NULL) {
74+
LOG_ERR("Failed to create pipeline");
75+
return 0;
76+
}
77+
78+
/* Add elements to the pipeline - order does not matter */
79+
if (mp_bin_add(MP_BIN(pipeline), source, transform, sink, NULL) == false) {
80+
LOG_ERR("Failed to add elements");
81+
return 0;
82+
}
83+
84+
/* Link elements together - order does matter */
85+
if (mp_element_link(source, transform, sink, NULL) == false) {
86+
LOG_ERR("Failed to link elements");
87+
return 0;
88+
}
89+
90+
/* Start playing */
91+
if (mp_element_set_state(pipeline, MP_STATE_PLAYING) != MP_STATE_CHANGE_SUCCESS) {
92+
LOG_ERR("Failed to start pipeline");
93+
return 0;
94+
}
95+
96+
/* Handle message from the pipeline */
97+
MpBus *bus = mp_element_get_bus(pipeline);
98+
/* Wait until an Error or an EOS - blocking */
99+
MpMessage *msg = mp_bus_pop_msg(bus, MP_MESSAGE_ERROR | MP_MESSAGE_EOS);
100+
if (msg != NULL) {
101+
switch (MP_MESSAGE_TYPE(msg)) {
102+
case MP_MESSAGE_ERROR:
103+
LOG_INF("Received ERROR from %s\n", msg->src->name);
104+
break;
105+
case MP_MESSAGE_EOS:
106+
LOG_INF("Received EOS from %s\n", msg->src->name);
107+
break;
108+
default:
109+
LOG_ERR("Unexpected message received from %s\n", msg->src->name);
110+
break;
111+
}
112+
}
113+
114+
/* TODO: Stop the pipeline */
115+
116+
return 0;
117+
}
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)