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