1212#include <sof/audio/format.h>
1313#include <sof/audio/pipeline.h>
1414#include <sof/audio/ipc-config.h>
15+ #include <module/audio/source_api.h>
16+ #include <module/audio/sink_api.h>
1517#include <sof/common.h>
1618#include <rtos/panic.h>
1719#include <sof/ipc/msg.h>
@@ -36,29 +38,39 @@ LOG_MODULE_REGISTER(mfcc, CONFIG_SOF_LOG_LEVEL);
3638
3739SOF_DEFINE_REG_UUID (mfcc );
3840
39- __cold_rodata const struct mfcc_func_map mfcc_fm [] = {
41+ /** \brief Source/sink API based source copy function map. */
42+ struct mfcc_source_func_map {
43+ uint8_t source ;
44+ mfcc_source_func func ;
45+ };
46+
47+ __cold_rodata static const struct mfcc_source_func_map mfcc_sfm [] = {
4048#if CONFIG_FORMAT_S16LE
41- {SOF_IPC_FRAME_S16_LE , mfcc_s16_default },
42- #endif /* CONFIG_FORMAT_S16LE */
49+ {SOF_IPC_FRAME_S16_LE , mfcc_source_copy_s16 },
50+ #endif
4351#if CONFIG_FORMAT_S24LE
44- {SOF_IPC_FRAME_S24_4LE , mfcc_s24_default },
45- #endif /* CONFIG_FORMAT_S24LE */
52+ {SOF_IPC_FRAME_S24_4LE , mfcc_source_copy_s24 },
53+ #endif
4654#if CONFIG_FORMAT_S32LE
47- {SOF_IPC_FRAME_S32_LE , mfcc_s32_default },
48- #endif /* CONFIG_FORMAT_S32LE */
55+ {SOF_IPC_FRAME_S32_LE , mfcc_source_copy_s32 },
56+ #endif
4957};
5058
51- static mfcc_func mfcc_find_func (enum sof_ipc_frame source_format ,
52- enum sof_ipc_frame sink_format ,
53- const struct mfcc_func_map * map ,
54- int n )
59+ /**
60+ * \brief Look up the source copy function for a given input format.
61+ *
62+ * \param[in] source_format SOF IPC frame format of the input stream.
63+ *
64+ * \return Pointer to the matching mfcc_source_func, or NULL if the
65+ * format is not supported in this build.
66+ */
67+ static mfcc_source_func mfcc_find_source_func (enum sof_ipc_frame source_format )
5568{
5669 int i ;
5770
58- /* Find suitable processing function from map. */
59- for (i = 0 ; i < n ; i ++ ) {
60- if (source_format == map [i ].source )
61- return map [i ].func ;
71+ for (i = 0 ; i < ARRAY_SIZE (mfcc_sfm ); i ++ ) {
72+ if (source_format == mfcc_sfm [i ].source )
73+ return mfcc_sfm [i ].func ;
6274 }
6375
6476 return NULL ;
@@ -68,6 +80,16 @@ static mfcc_func mfcc_find_func(enum sof_ipc_frame source_format,
6880 * End of MFCC setup code. Next the standard component methods.
6981 */
7082
83+ /**
84+ * \brief MFCC module init callback.
85+ *
86+ * Allocates the component private data and the configuration blob
87+ * handler used to receive the MFCC configuration from user space.
88+ *
89+ * \param[in,out] mod Processing module being initialized.
90+ *
91+ * \return 0 on success, -ENOMEM on allocation failure.
92+ */
7193static int mfcc_init (struct processing_module * mod )
7294{
7395 struct module_data * md = & mod -> priv ;
@@ -92,6 +114,16 @@ static int mfcc_init(struct processing_module *mod)
92114 return 0 ;
93115}
94116
117+ /**
118+ * \brief MFCC module free callback.
119+ *
120+ * Releases the IPC notification message, configuration blob handler,
121+ * runtime buffers and the private data structure.
122+ *
123+ * \param[in,out] mod Processing module being freed.
124+ *
125+ * \return 0 on success.
126+ */
95127static int mfcc_free (struct processing_module * mod )
96128{
97129 struct mfcc_comp_data * cd = module_get_private_data (mod );
@@ -106,27 +138,74 @@ static int mfcc_free(struct processing_module *mod)
106138}
107139
108140
141+ /**
142+ * \brief Source/sink API based process function for MFCC.
143+ *
144+ * Reads input audio from sof_source, runs the STFT/Mel/DCT stage, and
145+ * delegates output formatting and commit handling to mfcc_common.c.
146+ *
147+ * \param[in,out] mod Processing module.
148+ * \param[in,out] sources Source array; only sources[0] is used.
149+ * \param[in] num_of_sources Number of sources (must be 1).
150+ * \param[in,out] sinks Sink array; only sinks[0] is used.
151+ * \param[in] num_of_sinks Number of sinks (must be 1).
152+ *
153+ * \return 0 on success, -ENODATA if no input frames are available,
154+ * or a negative error code from the STFT or output stages.
155+ */
109156static int mfcc_process (struct processing_module * mod ,
110- struct input_stream_buffer * input_buffers , int num_input_buffers ,
111- struct output_stream_buffer * output_buffers , int num_output_buffers )
157+ struct sof_source * * sources , int num_of_sources ,
158+ struct sof_sink * * sinks , int num_of_sinks )
112159{
113160 struct mfcc_comp_data * cd = module_get_private_data (mod );
114- struct audio_stream * source = input_buffers -> data ;
115- struct audio_stream * sink = output_buffers -> data ;
116- int frames = input_buffers -> size ;
161+ struct comp_dev * dev = mod -> dev ;
162+ struct mfcc_state * state = & cd -> state ;
163+ bool pending ;
164+ size_t source_avail ;
165+ int frames ;
166+ int num_ceps ;
117167
118- comp_dbg (mod -> dev , "start" );
168+ comp_dbg (dev , "start" );
119169
120- frames = MIN (frames , cd -> max_frames );
121- cd -> mfcc_func (mod , input_buffers , output_buffers , frames );
170+ /* In compress mode, retry pending output first and avoid producing
171+ * new frames until previous frame has been committed.
172+ */
173+ pending = state -> header_pending || state -> out_remain > 0 ;
174+ if (cd -> config -> compress_output && pending )
175+ return mfcc_process_output (mod , cd , sources , sinks , 0 , 0 );
122176
123- /* TODO: use module_update_buffer_position() from #6194 */
124- input_buffers -> consumed += audio_stream_frame_bytes (source ) * frames ;
125- output_buffers -> size += audio_stream_frame_bytes (sink ) * frames ;
126- comp_dbg (mod -> dev , "done" );
127- return 0 ;
177+ source_avail = source_get_data_frames_available (sources [0 ]);
178+ frames = MIN (source_avail , cd -> max_frames );
179+ if (frames == 0 )
180+ return - ENODATA ;
181+
182+ /* Copy input audio from source to MFCC internal circular buffer */
183+ cd -> source_func (sources [0 ], & state -> buf , & state -> emph , frames , state -> source_channel );
184+
185+ /* Run STFT and Mel/DCT processing */
186+ num_ceps = mfcc_stft_process (mod , cd );
187+ if (num_ceps < 0 )
188+ return num_ceps ;
189+
190+ return mfcc_process_output (mod , cd , sources , sinks , num_ceps , frames );
128191}
129192
193+ /**
194+ * \brief MFCC module prepare callback.
195+ *
196+ * Validates the source/sink connection, reads the configuration blob,
197+ * initializes the MFCC processing state via mfcc_setup(), selects the
198+ * input copy function for the source frame format, and prepares the
199+ * VAD switch control notification when enabled.
200+ *
201+ * \param[in,out] mod Processing module being prepared.
202+ * \param[in,out] sources Source array; only sources[0] is used.
203+ * \param[in] num_of_sources Number of sources (must be 1).
204+ * \param[in,out] sinks Sink array; only sinks[0] is used.
205+ * \param[in] num_of_sinks Number of sinks (must be 1).
206+ *
207+ * \return 0 on success or a negative error code.
208+ */
130209static int mfcc_prepare (struct processing_module * mod ,
131210 struct sof_source * * sources , int num_of_sources ,
132211 struct sof_sink * * sinks , int num_of_sinks )
@@ -172,13 +251,21 @@ static int mfcc_prepare(struct processing_module *mod,
172251 return - EINVAL ;
173252 }
174253
175- cd -> mfcc_func = mfcc_find_func (source_format , sink_format , mfcc_fm , ARRAY_SIZE ( mfcc_fm ) );
176- if (!cd -> mfcc_func ) {
177- comp_err (dev , "No proc func" );
254+ cd -> source_func = mfcc_find_source_func (source_format );
255+ if (!cd -> source_func ) {
256+ comp_err (dev , "No source func" );
178257 mfcc_free_buffers (mod );
179258 return - EINVAL ;
180259 }
181260
261+ cd -> source_format = source_format ;
262+
263+ if (cd -> config -> compress_output )
264+ comp_info (dev , "compress PCM output mode enabled" );
265+
266+ if (cd -> config -> enable_dtx && !cd -> config -> compress_output )
267+ comp_warn (dev , "enable_dtx ignored in normal PCM mode, only applies to compress" );
268+
182269 /* Initialize VAD switch control notification if enabled */
183270 if (cd -> config -> enable_vad && cd -> config -> update_controls ) {
184271 if (!cd -> msg ) {
@@ -194,6 +281,17 @@ static int mfcc_prepare(struct processing_module *mod,
194281 return 0 ;
195282}
196283
284+ /**
285+ * \brief MFCC module reset callback.
286+ *
287+ * Frees runtime buffers (NULLing their pointers) so a subsequent
288+ * mfcc_prepare() can re-allocate cleanly. The configuration blob
289+ * handler and IPC notification message are preserved.
290+ *
291+ * \param[in,out] mod Processing module being reset.
292+ *
293+ * \return 0 on success.
294+ */
197295static int mfcc_reset (struct processing_module * mod )
198296{
199297 struct mfcc_comp_data * cd = module_get_private_data (mod );
@@ -206,7 +304,7 @@ static int mfcc_reset(struct processing_module *mod)
206304 mfcc_free_buffers (mod );
207305
208306 /* Reset to similar state as init() */
209- cd -> mfcc_func = NULL ;
307+ cd -> source_func = NULL ;
210308 return 0 ;
211309}
212310
@@ -215,7 +313,7 @@ static const struct module_interface mfcc_interface = {
215313 .free = mfcc_free ,
216314 .set_configuration = mfcc_set_config ,
217315 .get_configuration = mfcc_get_config ,
218- .process_audio_stream = mfcc_process ,
316+ .process = mfcc_process ,
219317 .prepare = mfcc_prepare ,
220318 .reset = mfcc_reset ,
221319};
0 commit comments