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: Virtual mixing audio output routines
29 *
30 * This file contains the actual mixing and resampling engine for output.
31 */
32
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35 #include <sys/sysmacros.h>
36 #include "audio_impl.h"
37
38 #define DECL_AUDIO_EXPORT(NAME, TYPE, SAMPLE) \
39 void \
40 auimpl_export_##NAME(audio_engine_t *eng, uint_t nfr, uint_t froff) \
41 { \
42 int nch = eng->e_nchan; \
43 uint_t hidx = eng->e_hidx; \
44 TYPE *out = (void *)eng->e_data; \
45 int ch = 0; \
46 \
47 do { /* for each channel */ \
48 int32_t *ip; \
49 TYPE *op; \
50 int i; \
51 int incr = eng->e_chincr[ch]; \
52 \
53 /* get value and adjust next channel offset */ \
54 op = out + eng->e_choffs[ch] + (hidx * incr); \
55 ip = eng->e_chbufs[ch]; \
56 ip += froff; \
57 \
58 i = nfr; \
59 \
60 do { /* for each frame */ \
61 int32_t sample = *ip; \
62 \
63 *op = SAMPLE; \
64 op += incr; \
65 ip++; \
66 \
67 } while (--i); \
68 \
69 ch++; \
70 } while (ch < nch); \
71 }
72
73 DECL_AUDIO_EXPORT(16ne, int16_t, sample >> 8)
74 DECL_AUDIO_EXPORT(16oe, int16_t, ddi_swap16(sample >> 8))
75 DECL_AUDIO_EXPORT(32ne, int32_t, sample << 8)
76 DECL_AUDIO_EXPORT(32oe, int32_t, ddi_swap32(sample << 8))
77 DECL_AUDIO_EXPORT(24ne, int32_t, sample)
78 DECL_AUDIO_EXPORT(24oe, int32_t, ddi_swap32(sample))
79
80 /*
81 * Simple limiter to prevent overflows when using fixed point computations
82 */
83 static void
auimpl_output_limiter(audio_engine_t * eng)84 auimpl_output_limiter(audio_engine_t *eng)
85 {
86 int k, t;
87 uint_t q, amp, amp2;
88 int nchan = eng->e_nchan;
89 uint_t fragfr = eng->e_fragfr;
90 int32_t **chbufs = eng->e_chbufs;
91 uint_t statevar = eng->e_limiter_state;
92
93 for (t = 0; t < fragfr; t++) {
94
95 amp = (uint_t)ABS(chbufs[0][t]);
96
97 for (k = 1; k < nchan; k++) {
98 amp2 = (uint_t)ABS(chbufs[k][t]);
99 if (amp2 > amp)
100 amp = amp2;
101 }
102
103 amp >>= 8;
104 q = 0x10000;
105
106 if (amp > 0x7FFF)
107 q = 0x7FFF0000 / amp;
108
109 if (statevar > q) {
110 statevar = q;
111 } else {
112 q = statevar;
113
114 /*
115 * Simplier (linear) tracking algo
116 * (gives less distortion, but more pumping)
117 */
118 statevar += 2;
119 if (statevar > 0x10000)
120 statevar = 0x10000;
121
122 /*
123 * Classic tracking algo
124 * gives more distortion with no-lookahead
125 * statevar=0x10000-((0x10000-statevar)*0xFFF4>>16);
126 */
127 }
128
129 for (k = 0; k < nchan; k++) {
130 int32_t in = chbufs[k][t];
131 int32_t out = 0;
132 uint_t p;
133
134 if (in >= 0) {
135 p = in;
136 p = ((p & 0xFFFF) * (q >> 4) >> 12) +
137 (p >> 16) * q;
138 out = p;
139 } else {
140 p = -in;
141 p = ((p & 0xFFFF) * (q >> 4) >> 12) +
142 (p >> 16) * q;
143 out = -p;
144 }
145 /* safety code */
146 /*
147 * if output after limiter is clamped, then it
148 * can be dropped
149 */
150 if (out > 0x7FFFFF)
151 out = 0x7FFFFF;
152 else if (out < -0x7FFFFF)
153 out = -0x7FFFFF;
154
155 chbufs[k][t] = out;
156 }
157 }
158
159 eng->e_limiter_state = statevar;
160 }
161
162 /*
163 * Output mixing function. Assumption: all work is done in 24-bit native PCM.
164 */
165 static void
auimpl_output_mix(audio_stream_t * sp,int offset,int nfr)166 auimpl_output_mix(audio_stream_t *sp, int offset, int nfr)
167 {
168 audio_engine_t *eng = sp->s_engine;
169 const int32_t *src;
170 int choffs;
171 int nch;
172 int vol;
173
174 /*
175 * Initial setup.
176 */
177
178 src = sp->s_cnv_ptr;
179 choffs = sp->s_choffs;
180 nch = sp->s_cnv_dst_nchan;
181 vol = sp->s_gain_eff;
182
183 /*
184 * Do the mixing. We de-interleave the source stream at the
185 * same time.
186 */
187 for (int ch = 0; ch < nch; ch++) {
188 int32_t *op;
189 const int32_t *ip;
190
191
192 ip = src + ch;
193 op = eng->e_chbufs[ch + choffs];
194 op += offset;
195
196 for (int i = nfr; i; i--) {
197
198 int64_t samp;
199
200 samp = *ip;
201 samp *= vol;
202 samp /= AUDIO_VOL_SCALE;
203
204 ip += nch;
205 *op += (int32_t)samp;
206 op++;
207 }
208 }
209
210 sp->s_cnv_cnt -= nfr;
211 sp->s_cnv_ptr += (nch * nfr);
212 }
213
214 /*
215 * Consume a fragment's worth of data. This is called when the data in
216 * the conversion buffer is exhausted, and we need to refill it from the
217 * source buffer. We always consume data from the client in quantities of
218 * a fragment at a time (assuming that a fragment is available.)
219 */
220 static void
auimpl_consume_fragment(audio_stream_t * sp)221 auimpl_consume_fragment(audio_stream_t *sp)
222 {
223 uint_t count;
224 uint_t avail;
225 uint_t nframes;
226 uint_t fragfr;
227 uint_t framesz;
228 caddr_t cnvbuf;
229
230 sp->s_cnv_src = sp->s_cnv_buf0;
231 sp->s_cnv_dst = sp->s_cnv_buf1;
232
233 fragfr = sp->s_fragfr;
234 nframes = sp->s_nframes;
235 framesz = sp->s_framesz;
236
237 ASSERT(sp->s_head >= sp->s_tail);
238
239 avail = sp->s_head - sp->s_tail;
240 cnvbuf = sp->s_cnv_src;
241
242 count = min(avail, fragfr);
243
244 /*
245 * Copy data. We deal properly with wraps. Done as a
246 * do...while to minimize the number of tests.
247 */
248 do {
249 uint_t n;
250 uint_t nbytes;
251
252 n = min(nframes - sp->s_tidx, count);
253 nbytes = framesz * n;
254 bcopy(sp->s_data + (sp->s_tidx * framesz), cnvbuf, nbytes);
255 cnvbuf += nbytes;
256 count -= n;
257 sp->s_samples += n;
258 sp->s_tail += n;
259 sp->s_tidx += n;
260 if (sp->s_tidx >= nframes)
261 sp->s_tidx -= nframes;
262 } while (count);
263
264 /* Note: data conversion is optional! */
265 count = min(avail, fragfr);
266 if (sp->s_converter != NULL) {
267 sp->s_cnv_cnt = sp->s_converter(sp, count);
268 } else {
269 sp->s_cnv_cnt = count;
270 }
271 }
272
273 static void
auimpl_output_callback_impl(audio_engine_t * eng,audio_client_t ** output,audio_client_t ** drain)274 auimpl_output_callback_impl(audio_engine_t *eng, audio_client_t **output,
275 audio_client_t **drain)
276 {
277 uint_t fragfr = eng->e_fragfr;
278 uint_t resid;
279
280 /* clear any preexisting mix results */
281 for (int i = 0; i < eng->e_nchan; i++)
282 bzero(eng->e_chbufs[i], AUDIO_CHBUFS * sizeof (int32_t));
283
284 for (audio_stream_t *sp = list_head(&eng->e_streams);
285 sp != NULL;
286 sp = list_next(&eng->e_streams, sp)) {
287
288 int need;
289 int avail;
290 int used;
291 int offset;
292 boolean_t drained = B_FALSE;
293 audio_client_t *c = sp->s_client;
294
295 /*
296 * We need/want a full fragment. If the client has
297 * less than that available, it will cause a client
298 * underrun in auimpl_consume_fragment, but in such a
299 * case we should get silence bytes. Assignments done
300 * ahead of the lock to minimize lock contention.
301 */
302 need = fragfr;
303 offset = 0;
304
305 mutex_enter(&sp->s_lock);
306 /* skip over streams not running or paused */
307 if ((!sp->s_running) || (sp->s_paused)) {
308 mutex_exit(&sp->s_lock);
309 continue;
310 }
311
312 do {
313 /* make sure we have data to chew on */
314 if ((avail = sp->s_cnv_cnt) == 0) {
315 auimpl_consume_fragment(sp);
316 sp->s_cnv_ptr = sp->s_cnv_src;
317 avail = sp->s_cnv_cnt;
318 }
319
320 /*
321 * We might have got more data than we need
322 * right now. (E.g. 8kHz expanding to 48kHz.)
323 * Take only what we need.
324 */
325 used = min(avail, need);
326
327 /*
328 * Mix the results, as much data as we can use
329 * this round.
330 */
331 auimpl_output_mix(sp, offset, used);
332
333 /*
334 * Save the offset for the next round, so we don't
335 * remix into the same location.
336 */
337 offset += used;
338
339 /*
340 * Okay, we mixed some data, but it might not
341 * have been all we need. This can happen
342 * either because we just mixed up some
343 * partial/residual data, or because the
344 * client has a fragment size which expands to
345 * less than a full fragment for us. (Such as
346 * a client wanting to operate at a higher
347 * data rate than the engine.)
348 */
349 need -= used;
350
351 } while (need && avail);
352
353 if (avail == 0) {
354 /* underrun or end of data */
355 if (sp->s_draining) {
356 if (sp->s_drain_idx == 0) {
357 sp->s_drain_idx = eng->e_head;
358 }
359 if (eng->e_tail >= sp->s_drain_idx) {
360 sp->s_drain_idx = 0;
361 sp->s_draining = B_FALSE;
362 /*
363 * After draining, stop the
364 * stream cleanly. This
365 * prevents underrun errors.
366 *
367 * (Stream will auto-start if
368 * client submits more data to
369 * it.)
370 *
371 * AC3: When an AC3 stream
372 * drains we should probably
373 * stop the actual hardware
374 * engine.
375 */
376 ASSERT(mutex_owned(&eng->e_lock));
377 sp->s_running = B_FALSE;
378 drained = B_TRUE;
379 }
380 } else {
381 sp->s_errors += need;
382 eng->e_stream_underruns++;
383 }
384 }
385
386 /* wake threads waiting for stream (blocking writes, etc.) */
387 cv_broadcast(&sp->s_cv);
388
389 mutex_exit(&sp->s_lock);
390
391
392 /*
393 * Asynchronously notify clients. We do as much as
394 * possible of this outside of the lock, it avoids
395 * s_lock and c_lock contention and eliminates any
396 * chance of deadlock.
397 */
398
399 /*
400 * NB: The only lock we are holding now is the engine
401 * lock. But the client can't go away because the
402 * closer would have to get the engine lock to remove
403 * the client's stream from engine. So we're safe.
404 */
405
406 if (output && (c->c_output != NULL) &&
407 (c->c_next_output == NULL)) {
408 auclnt_hold(c);
409 c->c_next_output = *output;
410 *output = c;
411 }
412
413 if (drain && drained && (c->c_drain != NULL) &&
414 (c->c_next_drain == NULL)) {
415 auclnt_hold(c);
416 c->c_next_drain = *drain;
417 *drain = c;
418 }
419 }
420
421 /*
422 * Deal with 24-bit overflows (from mixing) gracefully.
423 */
424 auimpl_output_limiter(eng);
425
426 /*
427 * Export the data (a whole fragment) to the device. Deal
428 * properly with wraps. Note that the test and subtraction is
429 * faster for dealing with wrap than modulo.
430 */
431 resid = fragfr;
432 do {
433 uint_t part = min(resid, eng->e_nframes - eng->e_hidx);
434 eng->e_export(eng, part, fragfr - resid);
435 eng->e_head += part;
436 eng->e_hidx += part;
437 if (eng->e_hidx == eng->e_nframes)
438 eng->e_hidx = 0;
439 resid -= part;
440 } while (resid);
441
442 /*
443 * Consider doing the SYNC outside of the lock.
444 */
445 ENG_SYNC(eng, fragfr);
446 }
447
448 /*
449 * Outer loop attempts to keep playing until we hit maximum playahead.
450 */
451
452 void
auimpl_output_callback(void * arg)453 auimpl_output_callback(void *arg)
454 {
455 audio_engine_t *e = arg;
456 int64_t cnt;
457 audio_client_t *c;
458 audio_client_t *output = NULL;
459 audio_client_t *drain = NULL;
460 uint64_t t;
461
462 mutex_enter(&e->e_lock);
463
464 if (e->e_suspended || e->e_failed || !e->e_periodic) {
465 mutex_exit(&e->e_lock);
466 return;
467 }
468
469 if (e->e_need_start) {
470 int rv;
471 if ((rv = ENG_START(e)) != 0) {
472 e->e_failed = B_TRUE;
473 mutex_exit(&e->e_lock);
474 audio_dev_warn(e->e_dev,
475 "failed starting output, rv = %d", rv);
476 return;
477 }
478 e->e_need_start = B_FALSE;
479 }
480
481 t = ENG_COUNT(e);
482 if (t < e->e_tail) {
483 /*
484 * This is a sign of a serious bug. We should
485 * probably offline the device via FMA, if we ever
486 * support FMA for audio devices.
487 */
488 e->e_failed = B_TRUE;
489 ENG_STOP(e);
490 mutex_exit(&e->e_lock);
491 audio_dev_warn(e->e_dev,
492 "device malfunction: broken play back sample counter");
493 return;
494
495 }
496 e->e_tail = t;
497
498 if (e->e_tail > e->e_head) {
499 /* want more than we have */
500 e->e_errors++;
501 e->e_underruns++;
502 }
503
504 cnt = e->e_head - e->e_tail;
505
506 /* stay a bit ahead */
507 while (cnt < e->e_playahead) {
508 auimpl_output_callback_impl(e, &output, &drain);
509 cnt = e->e_head - e->e_tail;
510 }
511 mutex_exit(&e->e_lock);
512
513 /*
514 * Notify client personalities.
515 */
516 while ((c = output) != NULL) {
517
518 output = c->c_next_output;
519 c->c_next_output = NULL;
520 c->c_output(c);
521 auclnt_release(c);
522 }
523
524 while ((c = drain) != NULL) {
525
526 drain = c->c_next_drain;
527 c->c_next_drain = NULL;
528 c->c_drain(c);
529 auclnt_release(c);
530 }
531
532 }
533
534 void
auimpl_output_preload(audio_engine_t * e)535 auimpl_output_preload(audio_engine_t *e)
536 {
537 int64_t cnt;
538
539 ASSERT(mutex_owned(&e->e_lock));
540
541 if (e->e_tail > e->e_head) {
542 /* want more than we have */
543 e->e_errors++;
544 e->e_underruns++;
545 e->e_tail = e->e_head;
546 }
547 cnt = e->e_head - e->e_tail;
548
549 /* stay a bit ahead */
550 while (cnt < e->e_playahead) {
551 auimpl_output_callback_impl(e, NULL, NULL);
552 cnt = e->e_head - e->e_tail;
553 }
554 }
555