xref: /illumos-gate/usr/src/uts/common/io/audio/impl/audio_format.c (revision 8883f1c270cc8e33c18dd088e744840092b47bbb)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (C) 4Front Technologies 1996-2008.
23  *
24  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
25  * Use is subject to license terms.
26  */
27 
28 /*
29  * Purpose: Audio format conversion routines used by audio.c
30  */
31 
32 #include <sys/types.h>
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35 #include <sys/audio/g711.h>
36 
37 #include "audio_impl.h"
38 #include "audio_grc3.h"
39 
40 
41 /*
42  * Note: In the function below, the division by the number of channels is
43  * probably fairly expensive.  It turns out that we usually deal with stereo
44  * or mono data, so perhaps it would be useful to build custom versions of
45  * this function that only dealt with stereo or mono.
46  */
47 static int
48 do_src(audio_stream_t *sp, void *p1, void *p2, int len, int nchan)
49 {
50 	int ch, size;
51 
52 	/*
53 	 * Note that we presume that we are doing sample rate
54 	 * conversions on AUDIO_FORMAT_S24_NE, which means that have 4
55 	 * byte and 32-bit samples.
56 	 */
57 	size = sp->s_cnv_max / 4;		/* sample size is 4 */
58 	size /= nchan;
59 
60 	for (ch = 0; ch < nchan; ch++) {
61 		grc3_convert(sp->s_src_state[ch], sp->s_src_quality,
62 		    p1, p2, len, size, nchan, ch);
63 	}
64 	return (((grc3state_t *)sp->s_src_state[0])->outsz);
65 }
66 
67 static void
68 setup_src(audio_stream_t *sp, int srate, int trate, int sch, int tch)
69 {
70 	int ch, nch;
71 
72 	nch = min(sch, tch);
73 
74 	ASSERT(nch <= AUDIO_MAX_CHANNELS);
75 
76 	if (sp->s_src_quality < 1)
77 		sp->s_src_quality = 1;
78 	if (sp->s_src_quality > 5)
79 		sp->s_src_quality = 5;
80 
81 	for (ch = 0; ch < nch; ch++) {
82 		grc3_reset(sp->s_src_state[ch]);
83 		grc3_setup(sp->s_src_state[ch], srate, trate);
84 	}
85 }
86 
87 static int
88 cnv_srconly(audio_stream_t *sp, int len)
89 {
90 	void *src = sp->s_cnv_src;
91 	void *dst = sp->s_cnv_dst;
92 
93 	/*
94 	 * We must be using 24-bit native signed.
95 	 */
96 	len = do_src(sp, src, dst, len, sp->s_cnv_src_nchan);
97 
98 	sp->s_cnv_src = dst;
99 	sp->s_cnv_dst = src;
100 
101 	return (len);
102 }
103 
104 static int
105 cnv_s24oe(audio_stream_t *sp, int len)
106 {
107 	/*
108 	 * Endian switch works in both directions.  We do it in place.
109 	 */
110 	int32_t *src = sp->s_cnv_src;
111 
112 	for (int i = len * sp->s_cnv_src_nchan; i; i--) {
113 		*src = ddi_swap32(*src);
114 		src++;
115 	}
116 
117 	return (len);
118 }
119 
120 
121 static int
122 cnv_from_s8(audio_stream_t *sp, int len)
123 {
124 	void *s = sp->s_cnv_src;
125 	void *d = sp->s_cnv_dst;
126 	int8_t *src = s;
127 	int32_t *dst = d;
128 
129 	for (int i = len * sp->s_cnv_src_nchan; i; i--)
130 		*dst++ = (*src++) << 16;
131 
132 	sp->s_cnv_src = d;
133 	sp->s_cnv_dst = s;
134 	return (len);
135 }
136 
137 static int
138 cnv_from_u8(audio_stream_t *sp, int len)
139 {
140 	void *s = sp->s_cnv_src;
141 	void *d = sp->s_cnv_dst;
142 	uint8_t *src = s;
143 	int32_t *dst = d;
144 
145 	for (int i = len * sp->s_cnv_src_nchan; i; i--)
146 		*dst++ = (int8_t)((*src++) ^ 0x80) << 16;
147 
148 	sp->s_cnv_src = d;
149 	sp->s_cnv_dst = s;
150 	return (len);
151 }
152 
153 static int
154 cnv_from_ulaw(audio_stream_t *sp, int len)
155 {
156 	void *s = sp->s_cnv_src;
157 	void *d = sp->s_cnv_dst;
158 	uint8_t *src = s;
159 	int32_t *dst = d;
160 
161 	for (int i = len * sp->s_cnv_src_nchan; i; i--) {
162 		*dst++ = _8ulaw2linear16[(*src++)] << 8;
163 	}
164 	sp->s_cnv_src = d;
165 	sp->s_cnv_dst = s;
166 	return (len);
167 }
168 
169 static int
170 cnv_from_alaw(audio_stream_t *sp, int len)
171 {
172 	void *s = sp->s_cnv_src;
173 	void *d = sp->s_cnv_dst;
174 	uint8_t *src = s;
175 	int32_t *dst = d;
176 
177 	for (int i = len * sp->s_cnv_src_nchan; i; i--) {
178 		*dst++ = _8alaw2linear16[(*src++)] << 8;
179 	}
180 	sp->s_cnv_src = d;
181 	sp->s_cnv_dst = s;
182 	return (len);
183 }
184 
185 static int
186 cnv_from_s16ne(audio_stream_t *sp, int len)
187 {
188 	void *s = sp->s_cnv_src;
189 	void *d = sp->s_cnv_dst;
190 	int16_t *src = s;
191 	int32_t *dst = d;
192 
193 	for (int i = len * sp->s_cnv_src_nchan; i; i--)
194 		*dst++ = (*src++) << 8;
195 
196 	sp->s_cnv_src = d;
197 	sp->s_cnv_dst = s;
198 	return (len);
199 }
200 
201 static int
202 cnv_from_s16oe(audio_stream_t *sp, int len)
203 {
204 	void *s = sp->s_cnv_src;
205 	void *d = sp->s_cnv_dst;
206 	int16_t *src = s;
207 	int32_t *dst = d;
208 
209 	for (int i = len * sp->s_cnv_src_nchan; i; i--)
210 		*dst++ = (int16_t)(ddi_swap16(*src++)) << 8;
211 
212 	sp->s_cnv_src = d;
213 	sp->s_cnv_dst = s;
214 	return (len);
215 }
216 
217 static int
218 cnv_from_u16ne(audio_stream_t *sp, int len)
219 {
220 	void *s = sp->s_cnv_src;
221 	void *d = sp->s_cnv_dst;
222 	uint16_t *src = s;
223 	int32_t *dst = d;
224 
225 	for (int i = len * sp->s_cnv_src_nchan; i; i--)
226 		*dst++ = (int16_t)((*src++) ^ 0x8000) << 8;
227 
228 	sp->s_cnv_src = d;
229 	sp->s_cnv_dst = s;
230 	return (len);
231 }
232 
233 static int
234 cnv_from_u16oe(audio_stream_t *sp, int len)
235 {
236 	void *s = sp->s_cnv_src;
237 	void *d = sp->s_cnv_dst;
238 	uint16_t *src = s;
239 	int32_t *dst = d;
240 
241 	for (int i = len * sp->s_cnv_src_nchan; i; i--)
242 		*dst++ = (int16_t)(ddi_swap16((*src++) ^ 0x8000)) << 8;
243 
244 	sp->s_cnv_src = d;
245 	sp->s_cnv_dst = s;
246 	return (len);
247 }
248 
249 static int
250 cnv_from_s24p(audio_stream_t *sp, int len)
251 {
252 	void *s = sp->s_cnv_src;
253 	void *d = sp->s_cnv_dst;
254 	uint8_t *src = s;
255 	int32_t *dst = d;
256 	int32_t tmp;
257 
258 	for (int i = len * sp->s_cnv_src_nchan; i; i--) {
259 		/* NB: this is a little endian format */
260 		tmp = (*src++);
261 		tmp |= (*src++) << 8;
262 		tmp |= (*src++) << 16;
263 		*dst++ = tmp;
264 	}
265 
266 	sp->s_cnv_src = d;
267 	sp->s_cnv_dst = s;
268 	return (len);
269 }
270 
271 static int
272 cnv_from_s32ne(audio_stream_t *sp, int len)
273 {
274 	/* 32-bit conversions can be done in place */
275 	int32_t *src = sp->s_cnv_src;
276 
277 	for (int i = len * sp->s_cnv_src_nchan; i; i--, src++)
278 		*src = *src >> 8;
279 
280 	return (len);
281 }
282 
283 static int
284 cnv_from_s32oe(audio_stream_t *sp, int len)
285 {
286 	/* 32-bit conversions can be done in place */
287 	int32_t *src = sp->s_cnv_src;
288 
289 	for (int i = len * sp->s_cnv_src_nchan; i; i--, src++)
290 		*src = (int32_t)(ddi_swap32(*src)) >> 8;
291 
292 	return (len);
293 }
294 
295 /*
296  * NB: All the destination format conversions use the same or fewer
297  * bytes as the 24-bit unpacked (32-bits used per sample), so we can
298  * convert all of them in place.
299  */
300 
301 static int
302 cnv_to_u8(audio_stream_t *sp, int len)
303 {
304 	int32_t *src = sp->s_cnv_src;
305 	uint8_t *dst = (void *)src;
306 
307 	for (int i = len * sp->s_cnv_dst_nchan; i; i--)
308 		*dst++ = (*src++ >> 16) ^ 0x80;
309 
310 	return (len);
311 }
312 
313 static int
314 cnv_to_s8(audio_stream_t *sp, int len)
315 {
316 	int32_t *src = sp->s_cnv_src;
317 	int8_t *dst = (void *)src;
318 
319 	for (int i = len * sp->s_cnv_dst_nchan; i; i--)
320 		*dst++ = *src++ >> 16;
321 
322 	return (len);
323 }
324 
325 static int
326 cnv_to_ulaw(audio_stream_t *sp, int len)
327 {
328 	int32_t *src = sp->s_cnv_src;
329 	uint8_t *dst = (void *)src;
330 
331 	for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
332 		int idx = *src++;
333 		idx >>= 10;
334 		idx += G711_ULAW_MIDPOINT;
335 		idx &= 0x3fff;	/* safety precaution */
336 		*dst++ = _14linear2ulaw8[idx];
337 	}
338 
339 	return (len);
340 }
341 
342 static int
343 cnv_to_alaw(audio_stream_t *sp, int len)
344 {
345 	int32_t *src = sp->s_cnv_src;
346 	uint8_t *dst = (void *)src;
347 
348 	for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
349 		int idx = *src++;
350 		idx >>= 11;
351 		idx += G711_ALAW_MIDPOINT;
352 		idx &= 0x1fff;	/* safety precaution */
353 		*dst++ = _13linear2alaw8[idx];
354 	}
355 
356 	return (len);
357 }
358 
359 static int
360 cnv_to_s16ne(audio_stream_t *sp, int len)
361 {
362 	int32_t *src = sp->s_cnv_src;
363 	int16_t *dst = (void *)src;
364 
365 	for (int i = len * sp->s_cnv_dst_nchan; i; i--)
366 		*dst++ = *src++ >> 8;
367 
368 	return (len);
369 }
370 
371 static int
372 cnv_to_s16oe(audio_stream_t *sp, int len)
373 {
374 	int32_t *src = sp->s_cnv_src;
375 	int16_t *dst = (void *)src;
376 
377 	for (int i = len * sp->s_cnv_dst_nchan; i; i--)
378 		*dst++ = ddi_swap16(*src++ >> 8);
379 
380 	return (len);
381 }
382 
383 static int
384 cnv_to_u16ne(audio_stream_t *sp, int len)
385 {
386 	int32_t *src = sp->s_cnv_src;
387 	uint16_t *dst = (void *)src;
388 
389 	for (int i = len * sp->s_cnv_dst_nchan; i; i--)
390 		*dst++ = (*src++ >> 8) ^ 0x8000;
391 
392 	return (len);
393 }
394 
395 static int
396 cnv_to_u16oe(audio_stream_t *sp, int len)
397 {
398 	int32_t *src = sp->s_cnv_src;
399 	uint16_t *dst = (void *)src;
400 
401 	for (int i = len * sp->s_cnv_dst_nchan; i; i--)
402 		*dst++ = ddi_swap16(*src++ >> 8) ^ 0x8000;
403 
404 	return (len);
405 }
406 
407 static int
408 cnv_to_s24p(audio_stream_t *sp, int len)
409 {
410 	int32_t *src = sp->s_cnv_src;
411 	uint8_t *dst = (void *)src;
412 	int32_t d;
413 
414 	for (int i = len * sp->s_cnv_dst_nchan; i; i--) {
415 		/* NB: this is a little endian format */
416 		d = *src++;
417 		*dst++ = d & 0xff;
418 		*dst++ = (d >> 8) & 0xff;
419 		*dst++ = (d >> 16) & 0xff;
420 	}
421 
422 	return (len);
423 }
424 
425 static int
426 cnv_to_s32ne(audio_stream_t *sp, int len)
427 {
428 	int32_t *src = sp->s_cnv_src;
429 
430 	for (int i = len * sp->s_cnv_dst_nchan; i; i--, src++)
431 		*src = *src << 8;
432 
433 	return (len);
434 }
435 
436 static int
437 cnv_to_s32oe(audio_stream_t *sp, int len)
438 {
439 	int32_t *src = sp->s_cnv_src;
440 
441 	for (int i = len * sp->s_cnv_dst_nchan; i; i--, src++)
442 		*src = ddi_swap32(*src << 8);
443 
444 	return (len);
445 }
446 
447 static int
448 cnv_default(audio_stream_t *sp, int len)
449 {
450 	/*
451 	 * Note that the formats were already preverified during
452 	 * select_converter, to ensure that only supported formats are
453 	 * used.
454 	 */
455 
456 	/*
457 	 * Convert samples to 24 bit (32 bit lsb aligned) if
458 	 * necessary.
459 	 */
460 
461 	switch (sp->s_cnv_src_format) {
462 
463 	case AUDIO_FORMAT_U8:
464 		len = cnv_from_u8(sp, len);
465 		break;
466 
467 	case AUDIO_FORMAT_S8:
468 		len = cnv_from_s8(sp, len);
469 		break;
470 
471 	case AUDIO_FORMAT_ULAW:
472 		len = cnv_from_ulaw(sp, len);
473 		break;
474 
475 	case AUDIO_FORMAT_ALAW:
476 		len = cnv_from_alaw(sp, len);
477 		break;
478 
479 	case AUDIO_FORMAT_S16_NE:
480 		len = cnv_from_s16ne(sp, len);
481 		break;
482 
483 	case AUDIO_FORMAT_S16_OE:
484 		len = cnv_from_s16oe(sp, len);
485 		break;
486 
487 	case AUDIO_FORMAT_U16_NE:
488 		len = cnv_from_u16ne(sp, len);
489 		break;
490 
491 	case AUDIO_FORMAT_U16_OE:
492 		len = cnv_from_u16oe(sp, len);
493 		break;
494 
495 	case AUDIO_FORMAT_S32_NE:
496 		len = cnv_from_s32ne(sp, len);
497 		break;
498 
499 	case AUDIO_FORMAT_S32_OE:
500 		len = cnv_from_s32oe(sp, len);
501 		break;
502 
503 	case AUDIO_FORMAT_S24_OE:
504 		len = cnv_s24oe(sp, len);
505 		break;
506 
507 	case AUDIO_FORMAT_S24_PACKED:
508 		len = cnv_from_s24p(sp, len);
509 		break;
510 	}
511 
512 	/*
513 	 * If we aren't decreasing the number of channels, then do the
514 	 * SRC now.  (We prefer to do SRC on the smaller number of channels.)
515 	 */
516 	if (sp->s_cnv_src_rate != sp->s_cnv_dst_rate &&
517 	    sp->s_cnv_src_nchan <= sp->s_cnv_dst_nchan) {
518 		int32_t *src = sp->s_cnv_src;
519 		int32_t *dst = sp->s_cnv_dst;
520 
521 		len = do_src(sp, src, dst, len, sp->s_cnv_src_nchan);
522 
523 		sp->s_cnv_src = dst;
524 		sp->s_cnv_dst = src;
525 	}
526 
527 	/*
528 	 * Convert between mono and stereo
529 	 */
530 
531 	if (sp->s_cnv_src_nchan != sp->s_cnv_dst_nchan) {
532 		int32_t *src = sp->s_cnv_src;
533 		int32_t *dst = sp->s_cnv_dst;
534 		int tc = sp->s_cnv_dst_nchan;
535 		int sc = sp->s_cnv_src_nchan;
536 		int nc;
537 		int i;
538 
539 		sp->s_cnv_src = dst;
540 		sp->s_cnv_dst = src;
541 
542 		if (sc == 1) {
543 			/*
544 			 * Mono expansion.  We expand into the stereo
545 			 * channel, and leave other channels silent.
546 			 */
547 			for (i = len; i; i--) {
548 				*dst++ = *src;
549 				*dst++ = *src++;
550 				for (int j = tc - 2; j > 0; j--) {
551 					*dst++ = 0;
552 				}
553 
554 			}
555 
556 		} else if (sc == 2 && tc == 1) {
557 			/*
558 			 * Stereo -> mono.  We do stereo separately to make
559 			 * the division fast (div by const 2 is just shift).
560 			 */
561 			for (i = len; i; i--) {
562 				/*
563 				 * Take just the left channel sample,
564 				 * discard the right channel.
565 				 */
566 				*dst++ = *src++;	/* left */
567 				src++;			/* right */
568 			}
569 		} else {
570 			/*
571 			 * Multi channel conversions.  We just copy the
572 			 * minimum number of channels.
573 			 */
574 
575 			/* Calculate number of frames */
576 
577 			nc = min(sc, tc);
578 
579 			/* Clear destination */
580 			bzero(dst, (len * tc * sizeof (int32_t)));
581 
582 			for (i = len; i; i--) {
583 				int c;
584 
585 				for (c = 0; c < nc; c++)
586 					dst[c] = src[c];
587 
588 				src += sc;
589 				dst += tc;
590 			}
591 		}
592 	}
593 
594 	/*
595 	 * If we didn't do SRC pre-conversion, then do it now.
596 	 */
597 	if (sp->s_cnv_src_rate != sp->s_cnv_dst_rate &&
598 	    sp->s_cnv_src_nchan > sp->s_cnv_dst_nchan) {
599 
600 		int32_t *src = sp->s_cnv_src;
601 		int32_t *dst = sp->s_cnv_dst;
602 
603 		len = do_src(sp, src, dst, len, sp->s_cnv_dst_nchan);
604 
605 		sp->s_cnv_src = dst;
606 		sp->s_cnv_dst = src;
607 	}
608 
609 	/*
610 	 * Finally convert samples from internal 24 bit format to target format
611 	 */
612 
613 	switch (sp->s_cnv_dst_format) {
614 	case AUDIO_FORMAT_U8:
615 		len = cnv_to_u8(sp, len);
616 		break;
617 
618 	case AUDIO_FORMAT_S8:
619 		len = cnv_to_s8(sp, len);
620 		break;
621 
622 	case AUDIO_FORMAT_S16_NE:
623 		len = cnv_to_s16ne(sp, len);
624 		break;
625 
626 	case AUDIO_FORMAT_S16_OE:
627 		len = cnv_to_s16oe(sp, len);
628 		break;
629 
630 	case AUDIO_FORMAT_U16_NE:
631 		len = cnv_to_u16ne(sp, len);
632 		break;
633 
634 	case AUDIO_FORMAT_U16_OE:
635 		len = cnv_to_u16oe(sp, len);
636 		break;
637 
638 	case AUDIO_FORMAT_S24_OE:
639 		len = cnv_s24oe(sp, len);
640 		break;
641 
642 	case AUDIO_FORMAT_S24_PACKED:
643 		len = cnv_to_s24p(sp, len);
644 		break;
645 
646 	case AUDIO_FORMAT_S32_NE:
647 		len = cnv_to_s32ne(sp, len);
648 		break;
649 
650 	case AUDIO_FORMAT_S32_OE:
651 		len = cnv_to_s32oe(sp, len);
652 		break;
653 
654 	case AUDIO_FORMAT_ULAW:
655 		len = cnv_to_ulaw(sp, len);
656 		break;
657 
658 	case AUDIO_FORMAT_ALAW:
659 		len = cnv_to_alaw(sp, len);
660 		break;
661 	}
662 
663 	return (len);
664 }
665 
666 static const struct audio_format_info {
667 	unsigned		format;
668 	int			sampsize;
669 	audio_cnv_func_t	from;
670 	audio_cnv_func_t	to;
671 } audio_format_info[] = {
672 	{ AUDIO_FORMAT_S8,	1,	cnv_from_s8,		cnv_to_s8 },
673 	{ AUDIO_FORMAT_U8,	1,	cnv_from_u8,		cnv_to_u8 },
674 	{ AUDIO_FORMAT_ULAW,	1,	cnv_from_ulaw,		cnv_to_ulaw },
675 	{ AUDIO_FORMAT_ALAW,	1,	cnv_from_alaw,		cnv_to_alaw },
676 	{ AUDIO_FORMAT_S16_NE,	2,	cnv_from_s16ne,		cnv_to_s16ne },
677 	{ AUDIO_FORMAT_S16_OE,	2,	cnv_from_s16oe,		cnv_to_s16oe },
678 	{ AUDIO_FORMAT_U16_NE,	2,	cnv_from_u16ne,		cnv_to_u16ne },
679 	{ AUDIO_FORMAT_U16_OE,	2,	cnv_from_u16oe,		cnv_to_u16oe },
680 	{ AUDIO_FORMAT_S32_NE,	4,	cnv_from_s32ne,		cnv_to_s32ne },
681 	{ AUDIO_FORMAT_S32_OE,	4,	cnv_from_s32oe,		cnv_to_s32oe },
682 
683 	/* 24-bit formats are "special" */
684 	{ AUDIO_FORMAT_S24_NE,	4,	NULL,			NULL },
685 	{ AUDIO_FORMAT_S24_OE,	4,	cnv_s24oe,		cnv_s24oe },
686 	{ AUDIO_FORMAT_S24_PACKED, 3,	cnv_from_s24p,		cnv_to_s24p },
687 
688 	/* sentinel */
689 	{ AUDIO_FORMAT_NONE,	0,	NULL,			NULL }
690 };
691 
692 int
693 auimpl_format_setup(audio_stream_t *sp, audio_parms_t *uparms)
694 {
695 	audio_parms_t			*source = &sp->s_cnv_src_parms;
696 	audio_parms_t			*target = &sp->s_cnv_dst_parms;
697 	audio_cnv_func_t		converter = NULL;
698 	const struct audio_format_info	*info;
699 	int				expand = AUDIO_UNIT_EXPAND;
700 	unsigned			cnv_sampsz = sizeof (uint32_t);
701 	unsigned			cnv_max;
702 
703 	if (sp == &sp->s_client->c_ostream) {
704 		source = uparms;
705 	} else {
706 		target = uparms;
707 	}
708 
709 	ASSERT(mutex_owned(&sp->s_lock));
710 
711 	/*
712 	 * At least one of the source or target are S24_NE.
713 	 *
714 	 * If we have a signed/native endian format, then pick an
715 	 * optimized converter.  While at it, ensure that a valid
716 	 * format is selected.
717 	 */
718 	if (source->p_format != AUDIO_FORMAT_S24_NE) {
719 		for (info = &audio_format_info[0]; info->sampsize; info++) {
720 			if (source->p_format == info->format) {
721 				converter = info->from;
722 				expand *= sizeof (int32_t);
723 				expand /= info->sampsize;
724 				/* save source frame size */
725 				cnv_sampsz = info->sampsize;
726 				break;
727 			}
728 		}
729 		if (info->format == AUDIO_FORMAT_NONE) {
730 			audio_dev_warn(sp->s_client->c_dev,
731 			    "invalid source format selected");
732 			return (EINVAL);
733 		}
734 
735 	} else if (target->p_format != AUDIO_FORMAT_S24_NE) {
736 		for (info = &audio_format_info[0]; info->sampsize; info++) {
737 			if (target->p_format == info->format) {
738 				converter = info->to;
739 				expand *= info->sampsize;
740 				expand /= sizeof (int32_t);
741 				break;
742 			}
743 		}
744 		if (info->format == AUDIO_FORMAT_NONE) {
745 			audio_dev_warn(sp->s_client->c_dev,
746 			    "invalid target format selected");
747 			return (EINVAL);
748 		}
749 	}
750 
751 	if (source->p_nchan != target->p_nchan) {
752 		/*
753 		 * if channels need conversion, then we must use the
754 		 * default.
755 		 */
756 		converter = cnv_default;
757 		expand *= target->p_nchan;
758 		expand /= source->p_nchan;
759 	}
760 
761 	if (source->p_rate != target->p_rate) {
762 		/*
763 		 * We need SRC; if we can avoid data conversion, do so.
764 		 */
765 		setup_src(sp, source->p_rate, target->p_rate,
766 		    source->p_nchan, target->p_nchan);
767 
768 		converter = (converter == NULL) ? cnv_srconly : cnv_default;
769 
770 		expand *= target->p_rate;
771 		expand /= source->p_rate;
772 	}
773 
774 	ASSERT(sp->s_engine);
775 	ASSERT(sp->s_engine->e_intrs);
776 
777 	/*
778 	 * Figure out the size of the conversion buffer we need.  We
779 	 * assume room for two full source fragments, which ought to
780 	 * be enough, even with rounding errors.
781 	 */
782 	cnv_max = 2 * (source->p_rate / sp->s_engine->e_intrs) *
783 	    cnv_sampsz * source->p_nchan;
784 
785 	/*
786 	 * If the conversion will cause us to expand fragments, then
787 	 * we need to increase cnv_max.  Scale by AUDIO_UNIT_EXPAND to
788 	 * avoid rouding errors or losing bits when doing reducing
789 	 * conversions.
790 	 */
791 	if (expand > AUDIO_UNIT_EXPAND) {
792 		cnv_max *= expand;
793 		cnv_max /= AUDIO_UNIT_EXPAND;
794 	}
795 
796 	/*
797 	 * Now we need to allocate space.
798 	 */
799 	if (sp->s_cnv_max < cnv_max) {
800 		uint32_t *buf0, *buf1;
801 
802 		buf0 = kmem_alloc(cnv_max, KM_NOSLEEP);
803 		buf1 = kmem_alloc(cnv_max, KM_NOSLEEP);
804 		if ((buf0 == NULL) || (buf1 == NULL)) {
805 			audio_dev_warn(sp->s_client->c_dev,
806 			    "failed to allocate audio conversion buffer "
807 			    "(%u bytes)", cnv_max);
808 			if (buf0)
809 				kmem_free(buf0, cnv_max);
810 			if (buf1)
811 				kmem_free(buf1, cnv_max);
812 			return (ENOMEM);
813 		}
814 
815 		if (sp->s_cnv_buf0)
816 			kmem_free(sp->s_cnv_buf0, sp->s_cnv_max);
817 		if (sp->s_cnv_buf1)
818 			kmem_free(sp->s_cnv_buf1, sp->s_cnv_max);
819 
820 		sp->s_cnv_buf0 = buf0;
821 		sp->s_cnv_buf1 = buf1;
822 		sp->s_cnv_max = cnv_max;
823 	}
824 
825 	/*
826 	 * NB: From here on, we must not fail.
827 	 */
828 
829 	/*
830 	 * Configure default fragment setup.
831 	 */
832 	for (info = &audio_format_info[0]; info->sampsize; info++) {
833 		if (uparms->p_format == info->format) {
834 			break;
835 		}
836 	}
837 	ASSERT(info->sampsize);
838 
839 	sp->s_framesz = info->sampsize * uparms->p_nchan;
840 	sp->s_fragfr = (uparms->p_rate / sp->s_engine->e_intrs);
841 	sp->s_fragbytes = sp->s_fragfr * sp->s_framesz;
842 	sp->s_nfrags = sp->s_allocsz / sp->s_fragbytes;
843 	sp->s_nframes = sp->s_nfrags * sp->s_fragfr;
844 	sp->s_nbytes = sp->s_nframes * sp->s_framesz;
845 	*sp->s_user_parms = *uparms;
846 	sp->s_converter = converter;
847 
848 	/*
849 	 * Ensure that we toss any stale data -- probably wrong format.
850 	 * Note that as a consequence of this, all of the offsets and
851 	 * counters get reset.  Clients should not rely on these values
852 	 * being preserved when changing formats.
853 	 *
854 	 * Its critical that we reset the indices, in particular,
855 	 * because not only will the data be the wrong format, but the
856 	 * indices themselves are quite possibly going to be invalid.
857 	 */
858 	sp->s_cnv_cnt = 0;
859 	sp->s_tail = sp->s_head = 0;
860 	sp->s_tidx = sp->s_hidx = 0;
861 
862 	return (0);
863 }
864 
865 int
866 auimpl_format_alloc(audio_stream_t *sp)
867 {
868 	int	i;
869 
870 	ASSERT(mutex_owned(&sp->s_lock));
871 	for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
872 		sp->s_src_state[i] =
873 		    kmem_zalloc(sizeof (grc3state_t), KM_NOSLEEP);
874 		if (sp->s_src_state[i] == NULL) {
875 			audio_dev_warn(sp->s_client->c_dev,
876 			    "unable to allocate SRC state structures");
877 			return (ENOMEM);
878 		}
879 	}
880 	return (0);
881 }
882 
883 void
884 auimpl_format_free(audio_stream_t *sp)
885 {
886 	int	i;
887 
888 	for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
889 		if (sp->s_src_state[i] != NULL) {
890 			kmem_free(sp->s_src_state[i], sizeof (grc3state_t));
891 			sp->s_src_state[i] = NULL;
892 		}
893 	}
894 }
895