xref: /illumos-gate/usr/src/uts/common/io/audio/impl/audio_output.c (revision 38603a2034ae521f26661b0a6239028a83026614)
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 #define	DECL_AUDIO_EXPORT(NAME, TYPE, SAMPLE)				\
40 void									\
41 auimpl_export_##NAME(audio_engine_t *eng)				\
42 {									\
43 	int		fragfr = eng->e_fragfr;				\
44 	int		nch = eng->e_nchan;				\
45 	unsigned	hidx = eng->e_hidx;				\
46 	TYPE		*out = (void *)eng->e_data;			\
47 	int		ch = 0;						\
48 									\
49 	do {	/* for each channel */					\
50 		int32_t *ip;						\
51 		TYPE	*op;						\
52 		int	i;						\
53 		int	incr = eng->e_chincr[ch];			\
54 									\
55 		/* get value and adjust next channel offset */		\
56 		op = out + eng->e_choffs[ch] + (hidx * incr);		\
57 		ip = eng->e_chbufs[ch];					\
58 									\
59 		i = fragfr;						\
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 
74 DECL_AUDIO_EXPORT(16ne, int16_t, sample >> 8)
75 DECL_AUDIO_EXPORT(16oe, int16_t, ddi_swap16(sample >> 8))
76 DECL_AUDIO_EXPORT(32ne, int32_t, sample << 8)
77 DECL_AUDIO_EXPORT(32oe, int32_t, ddi_swap32(sample << 8))
78 DECL_AUDIO_EXPORT(24ne, int32_t, sample)
79 DECL_AUDIO_EXPORT(24oe, int32_t, ddi_swap32(sample))
80 
81 /*
82  * Simple limiter to prevent overflows when using fixed point computations
83  */
84 static void
85 auimpl_output_limiter(audio_engine_t *eng)
86 {
87 	int k, t;
88 	unsigned int q, amp, amp2;
89 	int nchan = eng->e_nchan;
90 	int fragfr = eng->e_fragfr;
91 	int32_t **chbufs = eng->e_chbufs;
92 	unsigned int statevar = eng->e_limiter_state;
93 
94 	for (t = 0; t < fragfr; t++) {
95 
96 		amp = (unsigned)ABS(chbufs[0][t]);
97 
98 		for (k = 1; k < nchan; k++)	{
99 			amp2 = (unsigned)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 			unsigned int 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  */
166 static void
167 auimpl_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  */
221 static void
222 auimpl_consume_fragment(audio_stream_t *sp)
223 {
224 	unsigned	count;
225 	unsigned	avail;
226 	unsigned	nframes;
227 	unsigned	fragfr;
228 	unsigned	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 		unsigned n;
251 		unsigned 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 
274 static void
275 auimpl_output_callback_impl(audio_engine_t *eng)
276 {
277 	int		fragfr = eng->e_fragfr;
278 
279 	/* clear any preexisting mix results */
280 	for (int i = 0; i < eng->e_nchan; i++)
281 		bzero(eng->e_chbufs[i], AUDIO_CHBUFS * sizeof (int32_t));
282 
283 	for (audio_stream_t *sp = list_head(&eng->e_streams);
284 	    sp != NULL;
285 	    sp = list_next(&eng->e_streams, sp)) {
286 
287 		int		need;
288 		int		avail;
289 		int		used;
290 		int		offset;
291 		boolean_t	drained = B_FALSE;
292 		audio_client_t	*c = sp->s_client;
293 
294 		/*
295 		 * We need/want a full fragment.  If the client has
296 		 * less than that available, it will cause a client
297 		 * underrun in auimpl_consume_fragment, but in such a
298 		 * case we should get silence bytes.  Assignments done
299 		 * ahead of the lock to minimize lock contention.
300 		 */
301 		need = fragfr;
302 		offset = 0;
303 
304 		mutex_enter(&sp->s_lock);
305 		/* skip over streams not running or paused */
306 		if ((!sp->s_running) || (sp->s_paused) || eng->e_suspended) {
307 			mutex_exit(&sp->s_lock);
308 			continue;
309 		}
310 
311 		do {
312 			/* make sure we have data to chew on */
313 			if ((avail = sp->s_cnv_cnt) == 0) {
314 				auimpl_consume_fragment(sp);
315 				sp->s_cnv_ptr = sp->s_cnv_src;
316 				avail = sp->s_cnv_cnt;
317 			}
318 
319 			/*
320 			 * We might have got more data than we need
321 			 * right now.  (E.g. 8kHz expanding to 48kHz.)
322 			 * Take only what we need.
323 			 */
324 			used = min(avail, need);
325 
326 			/*
327 			 * Mix the results, as much data as we can use
328 			 * this round.
329 			 */
330 			auimpl_output_mix(sp, offset, used);
331 
332 			/*
333 			 * Save the offset for the next round, so we don't
334 			 * remix into the same location.
335 			 */
336 			offset += used;
337 
338 			/*
339 			 * Okay, we mixed some data, but it might not
340 			 * have been all we need.  This can happen
341 			 * either because we just mixed up some
342 			 * partial/residual data, or because the
343 			 * client has a fragment size which expands to
344 			 * less than a full fragment for us. (Such as
345 			 * a client wanting to operate at a higher
346 			 * data rate than the engine.)
347 			 */
348 			need -= used;
349 
350 		} while (need && avail);
351 
352 		if (avail == 0) {
353 			/* underrun or end of data */
354 			if (sp->s_draining) {
355 				if (sp->s_drain_idx == 0) {
356 					sp->s_drain_idx = eng->e_head;
357 				}
358 				if (eng->e_tail >= sp->s_drain_idx) {
359 					sp->s_drain_idx = 0;
360 					sp->s_draining = B_FALSE;
361 					/*
362 					 * After draining, stop the
363 					 * stream cleanly.  This
364 					 * prevents underrun errors.
365 					 *
366 					 * (Stream will auto-start if
367 					 * client submits more data to
368 					 * it.)
369 					 *
370 					 * AC3: When an AC3 stream
371 					 * drains we should probably
372 					 * stop the actual hardware
373 					 * engine.
374 					 */
375 					ASSERT(mutex_owned(&eng->e_lock));
376 					sp->s_running = B_FALSE;
377 					drained = B_TRUE;
378 				}
379 			} else {
380 				sp->s_errors += need;
381 				eng->e_stream_underruns++;
382 			}
383 		}
384 
385 		/* wake threads waiting for stream (blocking writes, etc.) */
386 		cv_broadcast(&sp->s_cv);
387 
388 		mutex_exit(&sp->s_lock);
389 
390 
391 		/*
392 		 * Asynchronously notify clients.  We do as much as
393 		 * possible of this outside of the lock, it avoids
394 		 * s_lock and c_lock contention and eliminates any
395 		 * chance of deadlock.
396 		 */
397 
398 		/*
399 		 * NB: The only lock we are holding now is the engine
400 		 * lock.  But the client can't go away because the
401 		 * closer would have to get the engine lock to remove
402 		 * the client's stream from engine.  So we're safe.
403 		 */
404 
405 		if (c->c_output != NULL) {
406 			c->c_output(c);
407 		}
408 
409 		if (drained && (c->c_drain != NULL)) {
410 			c->c_drain(c);
411 		}
412 	}
413 
414 	/*
415 	 * Deal with 24-bit overflows (from mixing) gracefully.
416 	 */
417 	auimpl_output_limiter(eng);
418 
419 	/*
420 	 * Export the data (a whole fragment) to the device.
421 	 */
422 	eng->e_export(eng);
423 
424 	/*
425 	 * Update the head and offset.  The head counts without
426 	 * wrapping, whereas the offset wraps.  Note that the test +
427 	 * subtraction is faster for dealing with wrap than modulo.
428 	 */
429 	eng->e_head += fragfr;
430 	eng->e_hidx += fragfr;
431 	if (eng->e_hidx >= eng->e_nframes)
432 		eng->e_hidx -= eng->e_nframes;
433 
434 	/*
435 	 * Consider doing the SYNC outside of the lock.
436 	 */
437 	ENG_SYNC(eng, fragfr);
438 }
439 
440 /*
441  * Outer loop attempts to keep playing until we hit maximum playahead.
442  */
443 
444 void
445 auimpl_output_callback(audio_engine_t *eng)
446 {
447 	unsigned fragfr;
448 	int64_t cnt;
449 
450 	fragfr = eng->e_fragfr;
451 	cnt = eng->e_head - eng->e_tail;
452 
453 	/* stay a bit ahead */
454 	while (cnt < ((fragfr * 3) / 2)) {
455 		auimpl_output_callback_impl(eng);
456 		cnt = eng->e_head - eng->e_tail;
457 	}
458 }
459