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)				\
39void									\
40auimpl_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
73DECL_AUDIO_EXPORT(16ne, int16_t, sample >> 8)
74DECL_AUDIO_EXPORT(16oe, int16_t, ddi_swap16(sample >> 8))
75DECL_AUDIO_EXPORT(32ne, int32_t, sample << 8)
76DECL_AUDIO_EXPORT(32oe, int32_t, ddi_swap32(sample << 8))
77DECL_AUDIO_EXPORT(24ne, int32_t, sample)
78DECL_AUDIO_EXPORT(24oe, int32_t, ddi_swap32(sample))
79
80/*
81 * Simple limiter to prevent overflows when using fixed point computations
82 */
83static void
84auimpl_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 */
165static void
166auimpl_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 */
220static void
221auimpl_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
273static void
274auimpl_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
452void
453auimpl_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
534void
535auimpl_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