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 underrun = B_FALSE; 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) || eng->e_suspended) { 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 underrun = B_TRUE; 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 mutex_enter(&c->c_lock); 401 c->c_do_output = B_TRUE; 402 403 if (underrun) 404 c->c_do_notify = B_TRUE; 405 406 if (drained) 407 c->c_do_drain = B_TRUE; 408 409 cv_broadcast(&c->c_cv); 410 mutex_exit(&c->c_lock); 411 } 412 413 /* 414 * Deal with 24-bit overflows (from mixing) gracefully. 415 */ 416 auimpl_output_limiter(eng); 417 418 /* 419 * Export the data (a whole fragment) to the device. 420 */ 421 eng->e_export(eng); 422 423 /* 424 * Update the head and offset. The head counts without 425 * wrapping, whereas the offset wraps. Note that the test + 426 * subtraction is faster for dealing with wrap than modulo. 427 */ 428 eng->e_head += fragfr; 429 eng->e_hidx += fragfr; 430 if (eng->e_hidx >= eng->e_nframes) 431 eng->e_hidx -= eng->e_nframes; 432 433 /* 434 * Consider doing the SYNC outside of the lock. 435 */ 436 ENG_SYNC(eng, fragfr); 437 } 438 439 /* 440 * Outer loop attempts to keep playing until we hit maximum playahead. 441 */ 442 443 void 444 auimpl_output_callback(audio_engine_t *eng) 445 { 446 unsigned fragfr; 447 int64_t cnt; 448 449 fragfr = eng->e_fragfr; 450 cnt = eng->e_head - eng->e_tail; 451 452 /* stay a bit ahead */ 453 while (cnt < (fragfr * 4)) { 454 auimpl_output_callback_impl(eng); 455 cnt = eng->e_head - eng->e_tail; 456 } 457 } 458