1 /**\r
2 * @file mss.c\r
3 * @brief Contains external API for Multi-Source Selection (MSS) module \r
4 * instantiation.\r
5 *\r
6 * Copyright (c) 2016, Texas Instruments Incorporated
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * * Neither the name of Texas Instruments Incorporated nor the names of
21 * its contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
30 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
31 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
33 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
34 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37 \r
38 #include <xdc/std.h>\r
39 #include <ti/mas/types/types.h>\r
40 #include <ti/mas/fract/fract.h>\r
41 #include <ti/mas/vpe/svd.h>\r
42 \r
43 //#include <ti/mas/aer/mss.h>\r
44 //#include <ti/mas/aer/src/mssloc.h>\r
45 #include "../mss.h"\r
46 #include "mssloc.h"\r
47 \r
48 #define MSS_DEF_SWITCH_WAIT_TIME 250 /* msec */\r
49 #define MSS_DEF_SWITCH_DURATION 500 /* msec */\r
50 #define MSS_DEF_SWITCH_HANGOVER 1000 /* msec */\r
51 #define MSS_DEF_FADE_PHA_INC_8KHZ 268435L /* Q31 phase increment of crossfade for \r
52 switch duration of 1 second at 8kHz:\r
53 2^31/8000, where 2^31 corresponds to pi. */\r
54 /* MSS memory buffer descriptors */\r
55 #define MSS_NUM_BUFS 1\r
56 #define MSS_INSTANCE_BUF 0\r
57 ecomemBuffer_t mssBufs[MSS_NUM_BUFS] = { \r
58 /* CLASS, LOG2 ALIGNMENT, BUFFER SIZE, VOLATILITY, BASE */\r
59 ecomem_CLASS_EXTERNAL, TYP_STRUCT_LOG2ALIGN, 0, FALSE, NULL\r
60 };\r
61 \r
62 /******************************************************************************\r
63 * FUNCTION PURPOSE: Return buffer sizes for the MSS module\r
64 ******************************************************************************\r
65 * DESCRIPTION: Calculate the worst case buffer sizes for the MSS. Also specify\r
66 * alignment and volatility requirements.\r
67 *\r
68 * tint mssGetSizes (\r
69 * tint *nbufs, - address to store number of buffers\r
70 * const ecomemBuffer_t **bufs, - address to store buffer descriptors\r
71 * mssSizeConfig_t *cfg) - information to be used in calculating the\r
72 * worst case buffer sizes\r
73 *****************************************************************************/\r
74 tint mssGetSizes(tint *nbufs, const ecomemBuffer_t **bufs, mssSizeConfig_t *cfg)\r
75 {\r
76 tint svd_size, mss_size, mss_inst_size, num_src;\r
77 \r
78 /* Get memory requirement of SVD */\r
79 svdGetSizes (&svd_size);\r
80 \r
81 /* Calculate total memory of MSS: instance + all SVDs*/\r
82 svd_size = mss_SIZE_ALIGN(svd_size,TYP_STRUCT_LOG2ALIGN);\r
83 mss_inst_size = sizeof(mssInst_t);\r
84 mss_inst_size = mss_SIZE_ALIGN(mss_inst_size,TYP_STRUCT_LOG2ALIGN);\r
85 num_src = cfg->max_num_mic_fixed + cfg->max_num_mic_remote\r
86 + cfg->max_num_mic_clean + cfg->max_num_beam;\r
87 mss_size = svd_size*num_src + mss_inst_size;\r
88 mssBufs[MSS_INSTANCE_BUF].size = mss_size;\r
89 \r
90 /* Return number of buffers required by MSS */ \r
91 *nbufs = MSS_NUM_BUFS;\r
92 \r
93 /* Return buffer specifications */\r
94 *bufs = &mssBufs[0]; \r
95 \r
96 return(mss_NOERR);\r
97 \r
98 } /* mssGetSizes */\r
99 \r
100 /******************************************************************************\r
101 * FUNCTION PURPOSE: Create an instance of the MSS module.\r
102 ******************************************************************************\r
103 * DESCRIPTION: Creates an instance of the MSS and initializes memory buffers.\r
104 *\r
105 * tint mssNew (\r
106 * void **mssInst, - address of the memory location that will\r
107 * receive a pointer to instance structure\r
108 * tint nbufs, - number of memory buffers\r
109 * ecomemBuffer_t *bufs, - a vector of buffer descriptors\r
110 * mssNewConfig_t *cfg) - a pointer to configuration structure\r
111 *\r
112 * Return value: \r
113 * mss_NOERR - success\r
114 * mss_ERR_INVALIDPAR - *mssInst is not NULL or nbufs is not correct \r
115 * mss_ERR_NOMEMORY - MSS instance pointer is not NULL, or\r
116 * number of buffers is not correct, or\r
117 * buffer properties are not correct\r
118 *****************************************************************************/\r
119 tint mssNew (void **mssInst, tint nbufs, ecomemBuffer_t *bufs, mssNewConfig_t *cfg)\r
120 {\r
121 mssInst_t *inst;\r
122 ecomemBuffer_t *bufp;\r
123 tint svd_size, mss_size, mss_inst_size, num_src;\r
124 int i;\r
125 \r
126 /* Test instance pointer (must be NULL) */\r
127 if ((*mssInst != NULL) || (nbufs != MSS_NUM_BUFS)) {\r
128 return(mss_ERR_INVALIDPAR);\r
129 }\r
130 \r
131 /* Check all dynamic buffers (base address != NULL) */\r
132 for (i=0, bufp=&bufs[0]; i<MSS_NUM_BUFS; i++, bufp++) {\r
133 if ((bufp->size>0) && (bufp->base==NULL)) {\r
134 return(mss_ERR_NOMEMORY);\r
135 }\r
136 }\r
137 \r
138 /* Get the instance buffer descriptor returned by the user */\r
139 bufp = &bufs[MSS_INSTANCE_BUF];\r
140 \r
141 /* Calculate total memory of MSS: instance + all SVDs */\r
142 svdGetSizes (&svd_size);\r
143 svd_size = mss_SIZE_ALIGN(svd_size,TYP_STRUCT_LOG2ALIGN);\r
144 mss_inst_size = sizeof(mssInst_t);\r
145 mss_inst_size = mss_SIZE_ALIGN(mss_inst_size,TYP_STRUCT_LOG2ALIGN);\r
146 num_src = cfg->sizeCfg.max_num_mic_fixed + cfg->sizeCfg.max_num_mic_remote\r
147 + cfg->sizeCfg.max_num_mic_clean + cfg->sizeCfg.max_num_beam;\r
148 mss_size = svd_size*num_src + mss_inst_size;\r
149 \r
150 /* Check if the provided memory is good: size, alignment, and volatility */\r
151 if ( (bufp->size < mss_size) \r
152 || (!typChkAlign(bufp->base, bufp->log2align)) || bufp->volat) {\r
153 return(mss_ERR_NOMEMORY);\r
154 }\r
155 \r
156 /* Assign instance memory and initialize instance */\r
157 inst = (mssInst_t *)bufp->base;\r
158 inst->max_sampling_rate = cfg->sizeCfg.max_sampling_rate;\r
159 inst->svd = (tword *)bufp->base + mss_inst_size; /* SVD address for 1st src */\r
160 inst->svd_size = svd_size;\r
161 inst->handle = cfg->handle; /* init handle in instance */\r
162 inst->state = MSS_CLOSED; /* set MSS state to CLOSED */\r
163 \r
164 /* Return instance address */\r
165 *mssInst = (void *)inst;\r
166 \r
167 return(mss_NOERR);\r
168 \r
169 } /* mssNew() */\r
170 \r
171 /******************************************************************************\r
172 * FUNCTION PURPOSE: Control of MSS\r
173 ******************************************************************************\r
174 * DESCRIPTION: Controls the operation and parameters of the MSS.\r
175 *\r
176 * tint mssControl (\r
177 * void *mssInst, - a pointer to MSS instance\r
178 * tint mssControl *ctl) - a pointer to the control code structure \r
179 *\r
180 * Return value: mss_NOERR - success\r
181 * mss_ERR_NOTOPENED - MSS not opened\r
182 * mss_ERR_INVALIDSRC - the manually selected source is invalid \r
183 * mss_ERR_INVALIDPAR - parameter is invalid \r
184 *****************************************************************************/\r
185 tint mssControl (void *mssInst, mssControl_t *ctl)\r
186 {\r
187 mssInst_t *inst = (mssInst_t *)mssInst;\r
188 tint ret_val;\r
189 \r
190 /* Make sure that MSS is open */\r
191 if (inst->state != MSS_OPEN) {\r
192 return (mss_ERR_NOTOPENED);\r
193 } \r
194 \r
195 ret_val = mss_NOERR;\r
196 \r
197 /* Change the operation modes bitfield */\r
198 if(mss_chkbit(ctl->valid_bitfield, mss_CTL_MODES)) {\r
199 inst->modes_bf = (inst->modes_bf & (~ctl->modes.mask))\r
200 | (ctl->modes.value & ctl->modes.mask);\r
201 } /* mss_CTL_MODES */\r
202 \r
203 /* Manually select source */\r
204 if(mss_chkbit(ctl->valid_bitfield, mss_CTL_SELECT_SRC)) {\r
205 /* Check if selected source is valid:\r
206 - source group must be one of the groups defined in mss.h, \r
207 - source index must be less than the number of sources in the group. */\r
208 if( (ctl->source.group > mss_SRC_MAX)\r
209 || (ctl->source.group < mss_SRC_MIC_FIXED) ){\r
210 ret_val = mss_ERR_INVALIDSRC;\r
211 } \r
212 else if (ctl->source.index > inst->num_src_per_group[ctl->source.group]) {\r
213 ret_val = mss_ERR_INVALIDSRC;\r
214 }\r
215 else if ( (ctl->source.group != inst->cur_src.group) \r
216 || (ctl->source.index != inst->cur_src.index) ) { \r
217 /* Prepare to switch source if selected source is valid. If in the middle of a \r
218 source switch initiated by MSS internally, internal switch will be stopped. */\r
219 inst->switch_src_cnt = 0;\r
220 inst->crossfade_phase = MSS_FADE_PHA_INIT;\r
221 inst->switch_hang_cnt = inst->params.switch_hangover;\r
222 inst->new_src = ctl->source;\r
223 mss_setbit(inst->state_bf, MSS_STATE_BIT_SWITCH_SRC);\r
224 }\r
225 } /* mss_CTL_SELECT_SRC */\r
226 \r
227 /* Change the threshold of source switch */\r
228 if(mss_chkbit(ctl->valid_bitfield, mss_CTL_SWITCH_THRESH)) {\r
229 /* Convert parameter from msec to # of samples */\r
230 inst->params.switch_threshold = MSS_NUM_SAMP_1MS_8KHZ * inst->sampling_rate\r
231 * ctl->switch_thresh;\r
232 }\r
233 \r
234 /* Change the duration of source switch */\r
235 if(mss_chkbit(ctl->valid_bitfield, mss_CTL_SWITCH_DURATION)) {\r
236 /* Convert parameter from msec to # of samples */\r
237 inst->params.switch_duration = MSS_NUM_SAMP_1MS_8KHZ * inst->sampling_rate\r
238 * ctl->switch_duration;\r
239 /* Calculate per sample Q31 phase increment for crossfade implementation: \r
240 2^31/duration, where 2^31 corresponds to pi. */ \r
241 inst->crossfade_phase_inc = frct_LFRCT_MAX/inst->params.switch_duration; \r
242 } /* mss_CTL_SWITCH_DURATION */\r
243 \r
244 /* Change hangover of source switch */\r
245 if(mss_chkbit(ctl->valid_bitfield, mss_CTL_SWITCH_HNAGOVER)) {\r
246 /* Convert parameter from msec to # of samples */\r
247 inst->params.switch_hangover = MSS_NUM_SAMP_1MS_8KHZ * inst->sampling_rate\r
248 * ctl->switch_hangover;\r
249 } /* mss_CTL_SWITCH_HNAGOVER */\r
250 \r
251 return ret_val;\r
252 } /* mssControl */\r
253 \r
254 /******************************************************************************\r
255 * FUNCTION PURPOSE: Open and configure an MSS instance.\r
256 ******************************************************************************\r
257 * DESCRIPTION: This function configures an instance of the MSS.\r
258 *\r
259 * tint mssOpen (\r
260 * void *mssInst, - a pointer to MSS instance\r
261 * mssConfig_t *cfg) - a pointer to MSS configuration structure\r
262 *\r
263 *****************************************************************************/\r
264 tint mssOpen (void *mssInst, mssConfig_t *cfg)\r
265 {\r
266 mssInst_t * inst = (mssInst_t *)mssInst;\r
267 tword * svd_ptr;\r
268 tint num_src, svd_size;\r
269 int i;\r
270 \r
271 /* Return error if state is not CLOSED */ \r
272 if(inst->state != MSS_CLOSED) {\r
273 return(mss_ERR_NOTCLOSED);\r
274 }\r
275 \r
276 /* Return error if no configuration parameters */\r
277 if(cfg == NULL){\r
278 return(mss_ERR_INVALIDPAR);\r
279 }\r
280 \r
281 /* Read configuration */\r
282 num_src = cfg->num_mic_fixed+cfg->num_mic_remote+cfg->num_mic_clean+cfg->num_beam;\r
283 if(num_src <= 0) {\r
284 return(mss_ERR_INVALIDPAR);\r
285 }\r
286 \r
287 inst->sampling_rate = cfg->sampling_rate;\r
288 inst->num_src_per_group[mss_SRC_MIC_FIXED] = cfg->num_mic_fixed;\r
289 inst->num_src_per_group[mss_SRC_MIC_REMOTE] = cfg->num_mic_remote;\r
290 inst->num_src_per_group[mss_SRC_MIC_CLEAN] = cfg->num_mic_clean;\r
291 inst->num_src_per_group[mss_SRC_BEAM] = cfg->num_beam;\r
292 inst->num_mic_array = cfg->num_mic_array; /* not considered as source to select */\r
293 \r
294 /* Init SVDs */\r
295 svd_size = inst->svd_size;\r
296 svd_ptr = (tword *)inst->svd;\r
297 for(i=0; i<num_src; i++) {\r
298 if (!typChkAlign(svd_ptr, TYP_STRUCT_LOG2ALIGN)) {\r
299 return(mss_ERR_NOMEMORY);\r
300 }\r
301 svdInit((void *)svd_ptr, inst->sampling_rate);\r
302 svd_ptr += svd_size;\r
303 } \r
304 \r
305 /* Set parameters to default */\r
306 inst->params.switch_threshold = MSS_DEF_SWITCH_WAIT_TIME * MSS_NUM_SAMP_1MS_8KHZ\r
307 * inst->sampling_rate; /* convert msec to # of samples */\r
308 inst->params.switch_duration = MSS_DEF_SWITCH_DURATION * MSS_NUM_SAMP_1MS_8KHZ\r
309 * inst->sampling_rate; /* convert msec to # of samples */\r
310 inst->crossfade_phase_inc = MSS_DEF_FADE_PHA_INC_8KHZ / inst->sampling_rate;\r
311 inst->params.switch_hangover = MSS_DEF_SWITCH_HANGOVER * MSS_NUM_SAMP_1MS_8KHZ \r
312 * inst->sampling_rate; /* convert msec to # of samples */\r
313 inst->modes_bf = mss_CTL_MODES_DEFAULT;\r
314 \r
315 /* Set initially selected source - the first valid source */\r
316 if(cfg->num_mic_fixed > 0) {\r
317 inst->cur_src.group = mss_SRC_MIC_FIXED;\r
318 inst->cur_src.index = 0;\r
319 }\r
320 else if(cfg->num_mic_remote > 0) {\r
321 inst->cur_src.group = mss_SRC_MIC_REMOTE;\r
322 inst->cur_src.index = 0;\r
323 }\r
324 else if(cfg->num_mic_clean > 0) {\r
325 inst->cur_src.group = mss_SRC_MIC_CLEAN;\r
326 inst->cur_src.index = 0;\r
327 }\r
328 else {\r
329 inst->cur_src.group = mss_SRC_BEAM;\r
330 inst->cur_src.index = 0;\r
331 }\r
332 \r
333 /* Initialize instance */ \r
334 inst->frame_size = inst->sampling_rate * MSS_FRAME_SIZE_8KHZ;\r
335 inst->switch_hang_cnt = inst->params.switch_hangover;\r
336 inst->crossfade_cnt = 0;\r
337 inst->state_bf = 0;\r
338 \r
339 /* Declare the instance OPEN */\r
340 inst->state = MSS_OPEN; \r
341 \r
342 return(mss_NOERR);\r
343 } /* mssOpen */\r
344 \r
345 /******************************************************************************\r
346 * FUNCTION PURPOSE: Returns debuging information for an MSS instance.\r
347 ******************************************************************************\r
348 * DESCRIPTION: This function returns debuging information.\r
349 *\r
350 * tint mssDebugStat (\r
351 * void *mssInst, - a pointer to MSS instance\r
352 * mssDebugStat_t *mssDbg) - a pointer to MSS debug structure\r
353 *\r
354 *****************************************************************************/\r
355 tint mssDebugStat(void *mssInst, mssDebugStat_t *mssDbg)\r
356 {\r
357 tint svd_decision;\r
358 tword *svd_ptr;\r
359 LFract sig_pow;\r
360 Fract spch_db, noise_db;\r
361 UFract svd_thresh;\r
362 mssInst_t *inst = (mssInst_t *)mssInst;\r
363 \r
364 /* Make sure that MSS is open */\r
365 if (inst->state != MSS_OPEN) {\r
366 return (mss_ERR_NOTOPENED);\r
367 } \r
368 \r
369 mssDbg->cur_src = inst->cur_src;\r
370 mssDbg->new_src = inst->new_src;\r
371 mssDbg->states[0] = (tuint)(inst->crossfade_phase>>16);\r
372 mssDbg->states[1] = (tuint)inst->gain_in;\r
373 mssDbg->states[2] = (tuint)inst->gain_out;\r
374 mssDbg->states[3] = (tuint)inst->switch_src_cnt; \r
375 mssDbg->states[4] = (tuint)inst->state_bf;\r
376 \r
377 /* only debug fixed mics for now */\r
378 if(inst->num_src_per_group[mss_SRC_MIC_FIXED] > 1) {\r
379 svd_ptr = inst->svd;\r
380 svd_decision = svdGetDecision(svd_ptr, &sig_pow);\r
381 mssDbg->states[5] = (tuint)svd_decision;\r
382 \r
383 svdGetLevels (svd_ptr, &spch_db, &noise_db, &svd_thresh);\r
384 mssDbg->states[6] = (tuint)spch_db;\r
385 mssDbg->states[7] = (tuint)noise_db;\r
386 \r
387 svd_ptr += inst->svd_size;\r
388 svd_decision = svdGetDecision(svd_ptr, &sig_pow);\r
389 mssDbg->states[8] = (tuint)svd_decision;\r
390 \r
391 svdGetLevels (svd_ptr, &spch_db, &noise_db, &svd_thresh);\r
392 mssDbg->states[9] = (tuint)spch_db;\r
393 mssDbg->states[10] = (tuint)noise_db;\r
394 }\r
395 \r
396 return(mss_NOERR);\r
397 \r
398 } /* mssDebugStat */\r
399 \r
400 /******************************************************************************\r
401 * FUNCTION PURPOSE: Close an instance of MSS.\r
402 ******************************************************************************\r
403 * DESCRIPTION: This function closes an instance of MSS by simply changing\r
404 * the state to CLOSED.\r
405 *\r
406 * tint mssClose (\r
407 * void *mssInst) - a pointer to MSS instance\r
408 *\r
409 *****************************************************************************/\r
410 tint mssClose (void *mssInst)\r
411 {\r
412 mssInst_t *inst = (mssInst_t *)mssInst;\r
413 \r
414 if(inst->state != MSS_OPEN) {\r
415 return(mss_ERR_NOTOPENED);\r
416 }\r
417 \r
418 /*Change the MSS state to CLOSED */\r
419 inst->state = MSS_CLOSED; \r
420 \r
421 return(mss_NOERR);\r
422 } /* mssClose */\r
423 \r
424 /******************************************************************************\r
425 * FUNCTION PURPOSE: Delete an MSS instance.\r
426 ******************************************************************************\r
427 * DESCRIPTION: Deletes an instance of MSS. Clears the instance pointer.\r
428 * Actual "deallocation" of instance should be done elsewhere\r
429 * after this function is called. Hence, one has to save the\r
430 * buffer descriptors to make "deallocation" possible.\r
431 *\r
432 * tint mssDelete (\r
433 * void **mssInst, - an address of memory location that contains\r
434 * a pointer to instance structure\r
435 * tint nbufs, - number of memory buffers\r
436 * ecomemBuffer_t *bufs) - vector of buffer descriptors\r
437 *\r
438 *****************************************************************************/\r
439 tint mssDelete (void **mssInst, tint nbufs, ecomemBuffer_t *bufs)\r
440 {\r
441 mssInst_t *inst = (mssInst_t *)*mssInst;\r
442 \r
443 /* check if instance is already closed */\r
444 if (inst->state != MSS_CLOSED) { \r
445 return (mss_ERR_NOTCLOSED);\r
446 }\r
447 \r
448 /* check if enough descriptors are provided to store all buffer addresses */\r
449 if (nbufs < MSS_NUM_BUFS) { \r
450 return (mss_ERR_NOMEMORY);\r
451 }\r
452 \r
453 /* return buffer addresses */\r
454 bufs[MSS_INSTANCE_BUF].base = inst; /* instance structure */\r
455 \r
456 /* clear the instance pointer */\r
457 *mssInst = NULL; \r
458 \r
459 return(mss_NOERR);\r
460 } /* mssDelete */\r
461 \r
462 /******************************************************************************\r
463 * FUNCTION PURPOSE: Validates the input sources to MSS.\r
464 ******************************************************************************\r
465 * DESCRIPTION: This function examines the input sources to MSS to make sure\r
466 * all sources are valid.\r
467 *\r
468 *****************************************************************************/\r
469 \r
470 tint mss_src_validation(mssInst_t *inst, void *rx_out_sync, void *mic_fix[],\r
471 void *mic_rem[], void *mic_cln[], void *mic_arr[], void *beam[])\r
472 { \r
473 int i;\r
474 \r
475 /* Return error if synchronized Rx out doesn't have valid data (NOT USED!!!) */\r
476 /*\r
477 * if ( rx_out_sync == NULL ) { \r
478 * return (mss_ERR_INVALIDSRC); \r
479 * }\r
480 */\r
481 \r
482 /* Check if all sources have valid data.\r
483 Currently MSS only supports fixed mic, remote mic, and clean mic.\r
484 */\r
485 if(inst->num_src_per_group[mss_SRC_MIC_FIXED] > 0) {\r
486 if(mic_fix == NULL) {\r
487 return (mss_ERR_INVALIDSRC);\r
488 }\r
489 else {\r
490 for (i=0; i<inst->num_src_per_group[mss_SRC_MIC_FIXED]; i++) {\r
491 if(mic_fix[i] == NULL) {\r
492 return (mss_ERR_INVALIDSRC);\r
493 }\r
494 }\r
495 }\r
496 } /* mss_SRC_MIC_FIXED */\r
497 \r
498 if(inst->num_src_per_group[mss_SRC_MIC_REMOTE] > 0) {\r
499 if(mic_rem == NULL) {\r
500 return (mss_ERR_INVALIDSRC);\r
501 }\r
502 else {\r
503 for (i=0; i<inst->num_src_per_group[mss_SRC_MIC_REMOTE]; i++) {\r
504 if(mic_rem[i] == NULL) {\r
505 return (mss_ERR_INVALIDSRC);\r
506 }\r
507 }\r
508 }\r
509 } /* mss_SRC_MIC_REMOTE */\r
510 \r
511 if(inst->num_src_per_group[mss_SRC_MIC_CLEAN] > 0) {\r
512 if(mic_cln == NULL) {\r
513 return (mss_ERR_INVALIDSRC);\r
514 }\r
515 else {\r
516 for (i=0; i<inst->num_src_per_group[mss_SRC_MIC_CLEAN]; i++) {\r
517 if(mic_cln[i] == NULL) {\r
518 return (mss_ERR_INVALIDSRC);\r
519 }\r
520 }\r
521 }\r
522 } /* mss_SRC_MIC_CLEAN */\r
523 \r
524 return (mss_NOERR); \r
525 } /* mss_src_validation */\r
526 \r
527 /* Nothing past this point */\r