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