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 (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25 */
26
27 /*
28 * Purpose: Audio format conversion routines used by audio.c
29 */
30
31 #include <sys/types.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/audio/g711.h>
35
36 #include "audio_impl.h"
37 #include "audio_grc3.h"
38
39 extern uint_t audio_intrhz;
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
do_src(audio_stream_t * sp,void * p1,void * p2,int len,int nchan)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
setup_src(audio_stream_t * sp,int srate,int trate,int sch,int tch)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
cnv_srconly(audio_stream_t * sp,int len)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
cnv_s24oe(audio_stream_t * sp,int len)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
cnv_from_s8(audio_stream_t * sp,int len)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
cnv_from_u8(audio_stream_t * sp,int len)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
cnv_from_ulaw(audio_stream_t * sp,int len)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
cnv_from_alaw(audio_stream_t * sp,int len)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
cnv_from_s16ne(audio_stream_t * sp,int len)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
cnv_from_s16oe(audio_stream_t * sp,int len)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
cnv_from_u16ne(audio_stream_t * sp,int len)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
cnv_from_u16oe(audio_stream_t * sp,int len)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
cnv_from_s24p(audio_stream_t * sp,int len)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
cnv_from_s32ne(audio_stream_t * sp,int len)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
cnv_from_s32oe(audio_stream_t * sp,int len)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
cnv_to_u8(audio_stream_t * sp,int len)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
cnv_to_s8(audio_stream_t * sp,int len)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
cnv_to_ulaw(audio_stream_t * sp,int len)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
cnv_to_alaw(audio_stream_t * sp,int len)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
cnv_to_s16ne(audio_stream_t * sp,int len)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
cnv_to_s16oe(audio_stream_t * sp,int len)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
cnv_to_u16ne(audio_stream_t * sp,int len)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
cnv_to_u16oe(audio_stream_t * sp,int len)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
cnv_to_s24p(audio_stream_t * sp,int len)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
cnv_to_s32ne(audio_stream_t * sp,int len)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
cnv_to_s32oe(audio_stream_t * sp,int len)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
cnv_default(audio_stream_t * sp,int len)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
auimpl_format_setup(audio_stream_t * sp,audio_parms_t * parms,uint_t mask)693 auimpl_format_setup(audio_stream_t *sp, audio_parms_t *parms, uint_t mask)
694 {
695 audio_parms_t source;
696 audio_parms_t target;
697 audio_parms_t *uparms;
698 audio_cnv_func_t converter = NULL;
699 const struct audio_format_info *info;
700 int expand = AUDIO_UNIT_EXPAND;
701 unsigned cnv_sampsz = sizeof (uint32_t);
702 unsigned cnv_max;
703 boolean_t needsrc = B_FALSE;
704
705 uint_t framesz;
706 uint_t fragfr;
707 uint_t fragbytes;
708 uint_t nfrags;
709
710 ASSERT(mutex_owned(&sp->s_lock));
711
712 source = sp->s_cnv_src_parms;
713 target = sp->s_cnv_dst_parms;
714
715 if (sp == &sp->s_client->c_ostream) {
716 if (mask & FORMAT_MSK_FMT)
717 source.p_format = parms->p_format;
718 if (mask & FORMAT_MSK_RATE)
719 source.p_rate = parms->p_rate;
720 if (mask & FORMAT_MSK_CHAN)
721 source.p_nchan = parms->p_nchan;
722 uparms = &source;
723 } else {
724 if (mask & FORMAT_MSK_FMT)
725 target.p_format = parms->p_format;
726 if (mask & FORMAT_MSK_RATE)
727 target.p_rate = parms->p_rate;
728 if (mask & FORMAT_MSK_CHAN)
729 target.p_nchan = parms->p_nchan;
730 uparms = ⌖
731 }
732
733 /*
734 * At least one of the source or target are S24_NE.
735 *
736 * If we have a signed/native endian format, then pick an
737 * optimized converter. While at it, ensure that a valid
738 * format is selected.
739 *
740 * After this function executes, "info" will point to the
741 * format information for the user parameters.
742 */
743 if (source.p_format != AUDIO_FORMAT_S24_NE) {
744 for (info = &audio_format_info[0]; info->sampsize; info++) {
745 if (source.p_format == info->format) {
746 converter = info->from;
747 expand *= sizeof (int32_t);
748 expand /= info->sampsize;
749 /* save source frame size */
750 cnv_sampsz = info->sampsize;
751 break;
752 }
753 }
754 } else {
755 /*
756 * Target format. Note that this case is also taken
757 * if we're operating on S24_NE data. In that case
758 * the converter will be NULL and expand will not be
759 * altered.
760 */
761 for (info = &audio_format_info[0]; info->sampsize; info++) {
762 if (target.p_format == info->format) {
763 converter = info->to;
764 expand *= info->sampsize;
765 expand /= sizeof (int32_t);
766 break;
767 }
768 }
769 }
770 if (info->format == AUDIO_FORMAT_NONE) {
771 audio_dev_warn(sp->s_client->c_dev, "invalid format selected");
772 return (EINVAL);
773 }
774
775
776 ASSERT(info->sampsize);
777
778 if (source.p_nchan != target.p_nchan) {
779 /*
780 * if channels need conversion, then we must use the
781 * default.
782 */
783 converter = cnv_default;
784 expand *= target.p_nchan;
785 expand /= source.p_nchan;
786 }
787
788 if (source.p_rate != target.p_rate) {
789 needsrc = B_TRUE;
790 converter = (converter == NULL) ? cnv_srconly : cnv_default;
791
792 expand *= target.p_rate;
793 expand /= source.p_rate;
794 }
795
796 /*
797 * Figure out the size of the conversion buffer we need. We
798 * assume room for two full source fragments, which ought to
799 * be enough, even with rounding errors.
800 */
801 cnv_max = 2 * (source.p_rate / audio_intrhz) *
802 cnv_sampsz * source.p_nchan;
803
804 /*
805 * If the conversion will cause us to expand fragments, then
806 * we need to increase cnv_max. Scale by AUDIO_UNIT_EXPAND to
807 * avoid rouding errors or losing bits when doing reducing
808 * conversions.
809 */
810 if (expand > AUDIO_UNIT_EXPAND) {
811 cnv_max *= expand;
812 cnv_max /= AUDIO_UNIT_EXPAND;
813 }
814
815 framesz = info->sampsize * uparms->p_nchan;
816 fragfr = (uparms->p_rate / audio_intrhz);
817 fragbytes = fragfr * framesz;
818
819 /*
820 * We need to "tune" the buffer and fragment counts for some
821 * uses... OSS applications may like to configure a low
822 * latency, and they rely upon write() to block to prevent too
823 * much data from being queued up.
824 */
825 if (sp->s_hintsz) {
826 nfrags = sp->s_hintsz / fragbytes;
827 } else if (sp->s_hintfrags) {
828 nfrags = sp->s_hintfrags;
829 } else {
830 nfrags = sp->s_allocsz / fragbytes;
831 }
832
833 /*
834 * Now make sure that the hint works -- we need at least 2 fragments,
835 * and we need to fit within the room allocated to us.
836 */
837 if (nfrags < 2) {
838 nfrags = 2;
839 }
840 while ((nfrags * fragbytes) > sp->s_allocsz) {
841 nfrags--;
842 }
843 /* if the resulting configuration is invalid, note it */
844 if (nfrags < 2) {
845 return (EINVAL);
846 }
847
848 /*
849 * Now we need to allocate space.
850 *
851 * NB: Once the allocation succeeds, we must not fail. We are
852 * modifying the the stream settings and these changes must be
853 * made atomically.
854 */
855 if (sp->s_cnv_max < cnv_max) {
856 uint32_t *buf0, *buf1;
857
858 buf0 = kmem_alloc(cnv_max, KM_NOSLEEP);
859 buf1 = kmem_alloc(cnv_max, KM_NOSLEEP);
860 if ((buf0 == NULL) || (buf1 == NULL)) {
861 audio_dev_warn(sp->s_client->c_dev,
862 "failed to allocate audio conversion buffer "
863 "(%u bytes)", cnv_max);
864 if (buf0)
865 kmem_free(buf0, cnv_max);
866 if (buf1)
867 kmem_free(buf1, cnv_max);
868 return (ENOMEM);
869 }
870
871 if (sp->s_cnv_buf0)
872 kmem_free(sp->s_cnv_buf0, sp->s_cnv_max);
873 if (sp->s_cnv_buf1)
874 kmem_free(sp->s_cnv_buf1, sp->s_cnv_max);
875
876 sp->s_cnv_buf0 = buf0;
877 sp->s_cnv_buf1 = buf1;
878 sp->s_cnv_max = cnv_max;
879 }
880
881 /* Set up the SRC state if we will be using SRC. */
882 if (needsrc) {
883 setup_src(sp, source.p_rate, target.p_rate,
884 source.p_nchan, target.p_nchan);
885 }
886
887
888 sp->s_framesz = framesz;
889 sp->s_fragfr = fragfr;
890 sp->s_fragbytes = fragbytes;
891 sp->s_nfrags = nfrags;
892 sp->s_nframes = nfrags * fragfr;
893 sp->s_nbytes = sp->s_nframes * framesz;
894 *sp->s_user_parms = *uparms;
895 sp->s_converter = converter;
896
897 /*
898 * Ensure that we toss any stale data -- probably wrong format.
899 * Note that as a consequence of this, all of the offsets and
900 * counters get reset. Clients should not rely on these values
901 * being preserved when changing formats.
902 *
903 * Its critical that we reset the indices, in particular,
904 * because not only will the data be the wrong format, but the
905 * indices themselves are quite possibly going to be invalid.
906 */
907 sp->s_cnv_cnt = 0;
908 sp->s_tail = sp->s_head = 0;
909 sp->s_tidx = sp->s_hidx = 0;
910
911 return (0);
912 }
913
914 int
auimpl_format_alloc(audio_stream_t * sp)915 auimpl_format_alloc(audio_stream_t *sp)
916 {
917 int i;
918
919 ASSERT(mutex_owned(&sp->s_lock));
920 for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
921 sp->s_src_state[i] =
922 kmem_zalloc(sizeof (grc3state_t), KM_NOSLEEP);
923 if (sp->s_src_state[i] == NULL) {
924 audio_dev_warn(sp->s_client->c_dev,
925 "unable to allocate SRC state structures");
926 return (ENOMEM);
927 }
928 }
929 return (0);
930 }
931
932 void
auimpl_format_free(audio_stream_t * sp)933 auimpl_format_free(audio_stream_t *sp)
934 {
935 int i;
936
937 for (i = 0; i < AUDIO_MAX_CHANNELS; i++) {
938 if (sp->s_src_state[i] != NULL) {
939 kmem_free(sp->s_src_state[i], sizeof (grc3state_t));
940 sp->s_src_state[i] = NULL;
941 }
942 }
943 }
944