1/*- 2 * Copyright (c) 2005-2009 Ariff Abdullah <ariff@FreeBSD.org> 3 * Portions Copyright (c) Ryan Beasley <ryan.beasley@gmail.com> - GSoC 2006 4 * Copyright (c) 1999 Cameron Grant <cg@FreeBSD.org> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#ifdef HAVE_KERNEL_OPTION_HEADERS 30#include "opt_snd.h" 31#endif 32 33#include <dev/sound/pcm/sound.h> 34 35#include "feeder_if.h" 36 37#define SND_USE_FXDIV 38#include "snd_fxdiv_gen.h" 39 40SND_DECLARE_FILE("$FreeBSD: releng/10.3/sys/dev/sound/pcm/buffer.c 243450 2012-11-23 13:43:51Z mav $"); 41 42struct snd_dbuf * 43sndbuf_create(device_t dev, char *drv, char *desc, struct pcm_channel *channel) 44{ 45 struct snd_dbuf *b; 46 47 b = malloc(sizeof(*b), M_DEVBUF, M_WAITOK | M_ZERO); 48 snprintf(b->name, SNDBUF_NAMELEN, "%s:%s", drv, desc); 49 b->dev = dev; 50 b->channel = channel; 51 52 return b; 53} 54 55void 56sndbuf_destroy(struct snd_dbuf *b) 57{ 58 sndbuf_free(b); 59 free(b, M_DEVBUF); 60} 61 62bus_addr_t 63sndbuf_getbufaddr(struct snd_dbuf *buf) 64{ 65 return (buf->buf_addr); 66} 67 68static void 69sndbuf_setmap(void *arg, bus_dma_segment_t *segs, int nseg, int error) 70{ 71 struct snd_dbuf *b = (struct snd_dbuf *)arg; 72 73 if (snd_verbose > 3) { 74 device_printf(b->dev, "sndbuf_setmap %lx, %lx; ", 75 (u_long)segs[0].ds_addr, (u_long)segs[0].ds_len); 76 printf("%p -> %lx\n", b->buf, (u_long)segs[0].ds_addr); 77 } 78 if (error == 0) 79 b->buf_addr = segs[0].ds_addr; 80 else 81 b->buf_addr = 0; 82} 83 84/* 85 * Allocate memory for DMA buffer. If the device does not use DMA transfers, 86 * the driver can call malloc(9) and sndbuf_setup() itself. 87 */ 88 89int 90sndbuf_alloc(struct snd_dbuf *b, bus_dma_tag_t dmatag, int dmaflags, 91 unsigned int size) 92{ 93 int ret; 94 95 b->dmatag = dmatag; 96 b->dmaflags = dmaflags | BUS_DMA_NOWAIT | BUS_DMA_COHERENT; 97 b->maxsize = size; 98 b->bufsize = b->maxsize; 99 b->buf_addr = 0; 100 b->flags |= SNDBUF_F_MANAGED; 101 if (bus_dmamem_alloc(b->dmatag, (void **)&b->buf, b->dmaflags, 102 &b->dmamap)) { 103 sndbuf_free(b); 104 return (ENOMEM); 105 } 106 if (bus_dmamap_load(b->dmatag, b->dmamap, b->buf, b->maxsize, 107 sndbuf_setmap, b, 0) != 0 || b->buf_addr == 0) { 108 sndbuf_free(b); 109 return (ENOMEM); 110 } 111 112 ret = sndbuf_resize(b, 2, b->maxsize / 2); 113 if (ret != 0) 114 sndbuf_free(b); 115 116 return (ret); 117} 118 119int 120sndbuf_setup(struct snd_dbuf *b, void *buf, unsigned int size) 121{ 122 b->flags &= ~SNDBUF_F_MANAGED; 123 if (buf) 124 b->flags |= SNDBUF_F_MANAGED; 125 b->buf = buf; 126 b->maxsize = size; 127 b->bufsize = b->maxsize; 128 return sndbuf_resize(b, 2, b->maxsize / 2); 129} 130 131void 132sndbuf_free(struct snd_dbuf *b) 133{ 134 if (b->tmpbuf) 135 free(b->tmpbuf, M_DEVBUF); 136 137 if (b->shadbuf) 138 free(b->shadbuf, M_DEVBUF); 139 140 if (b->buf) { 141 if (b->flags & SNDBUF_F_MANAGED) { 142 if (b->dmamap) 143 bus_dmamap_unload(b->dmatag, b->dmamap); 144 if (b->dmatag) 145 bus_dmamem_free(b->dmatag, b->buf, b->dmamap); 146 } else 147 free(b->buf, M_DEVBUF); 148 } 149 150 b->tmpbuf = NULL; 151 b->shadbuf = NULL; 152 b->buf = NULL; 153 b->sl = 0; 154 b->dmatag = NULL; 155 b->dmamap = NULL; 156} 157 158#define SNDBUF_CACHE_SHIFT 5 159 160int 161sndbuf_resize(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) 162{ 163 unsigned int bufsize, allocsize; 164 u_int8_t *tmpbuf; 165 166 CHN_LOCK(b->channel); 167 if (b->maxsize == 0) 168 goto out; 169 if (blkcnt == 0) 170 blkcnt = b->blkcnt; 171 if (blksz == 0) 172 blksz = b->blksz; 173 if (blkcnt < 2 || blksz < 16 || (blkcnt * blksz) > b->maxsize) { 174 CHN_UNLOCK(b->channel); 175 return EINVAL; 176 } 177 if (blkcnt == b->blkcnt && blksz == b->blksz) 178 goto out; 179 180 bufsize = blkcnt * blksz; 181 182 if (bufsize > b->allocsize || 183 bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) { 184 allocsize = round_page(bufsize); 185 CHN_UNLOCK(b->channel); 186 tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); 187 CHN_LOCK(b->channel); 188 if (snd_verbose > 3) 189 printf("%s(): b=%p %p -> %p [%d -> %d : %d]\n", 190 __func__, b, b->tmpbuf, tmpbuf, 191 b->allocsize, allocsize, bufsize); 192 if (b->tmpbuf != NULL) 193 free(b->tmpbuf, M_DEVBUF); 194 b->tmpbuf = tmpbuf; 195 b->allocsize = allocsize; 196 } else if (snd_verbose > 3) 197 printf("%s(): b=%p %d [%d] NOCHANGE\n", 198 __func__, b, b->allocsize, b->bufsize); 199 200 b->blkcnt = blkcnt; 201 b->blksz = blksz; 202 b->bufsize = bufsize; 203 204 sndbuf_reset(b); 205out: 206 CHN_UNLOCK(b->channel); 207 return 0; 208} 209 210int 211sndbuf_remalloc(struct snd_dbuf *b, unsigned int blkcnt, unsigned int blksz) 212{ 213 unsigned int bufsize, allocsize; 214 u_int8_t *buf, *tmpbuf, *shadbuf; 215 216 if (blkcnt < 2 || blksz < 16) 217 return EINVAL; 218 219 bufsize = blksz * blkcnt; 220 221 if (bufsize > b->allocsize || 222 bufsize < (b->allocsize >> SNDBUF_CACHE_SHIFT)) { 223 allocsize = round_page(bufsize); 224 CHN_UNLOCK(b->channel); 225 buf = malloc(allocsize, M_DEVBUF, M_WAITOK); 226 tmpbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); 227 shadbuf = malloc(allocsize, M_DEVBUF, M_WAITOK); 228 CHN_LOCK(b->channel); 229 if (b->buf != NULL) 230 free(b->buf, M_DEVBUF); 231 b->buf = buf; 232 if (b->tmpbuf != NULL) 233 free(b->tmpbuf, M_DEVBUF); 234 b->tmpbuf = tmpbuf; 235 if (b->shadbuf != NULL) 236 free(b->shadbuf, M_DEVBUF); 237 b->shadbuf = shadbuf; 238 if (snd_verbose > 3) 239 printf("%s(): b=%p %d -> %d [%d]\n", 240 __func__, b, b->allocsize, allocsize, bufsize); 241 b->allocsize = allocsize; 242 } else if (snd_verbose > 3) 243 printf("%s(): b=%p %d [%d] NOCHANGE\n", 244 __func__, b, b->allocsize, b->bufsize); 245 246 b->blkcnt = blkcnt; 247 b->blksz = blksz; 248 b->bufsize = bufsize; 249 b->maxsize = bufsize; 250 b->sl = bufsize; 251 252 sndbuf_reset(b); 253 254 return 0; 255} 256 257/** 258 * @brief Zero out space in buffer free area 259 * 260 * This function clears a chunk of @c length bytes in the buffer free area 261 * (i.e., where the next write will be placed). 262 * 263 * @param b buffer context 264 * @param length number of bytes to blank 265 */ 266void 267sndbuf_clear(struct snd_dbuf *b, unsigned int length) 268{ 269 int i; 270 u_char data, *p; 271 272 if (length == 0) 273 return; 274 if (length > b->bufsize) 275 length = b->bufsize; 276 277 data = sndbuf_zerodata(b->fmt); 278 279 i = sndbuf_getfreeptr(b); 280 p = sndbuf_getbuf(b); 281 while (length > 0) { 282 p[i] = data; 283 length--; 284 i++; 285 if (i >= b->bufsize) 286 i = 0; 287 } 288} 289 290/** 291 * @brief Zap buffer contents, resetting "ready area" fields 292 * 293 * @param b buffer context 294 */ 295void 296sndbuf_fillsilence(struct snd_dbuf *b) 297{ 298 if (b->bufsize > 0) 299 memset(sndbuf_getbuf(b), sndbuf_zerodata(b->fmt), b->bufsize); 300 b->rp = 0; 301 b->rl = b->bufsize; 302} 303 304void 305sndbuf_fillsilence_rl(struct snd_dbuf *b, u_int rl) 306{ 307 if (b->bufsize > 0) 308 memset(sndbuf_getbuf(b), sndbuf_zerodata(b->fmt), b->bufsize); 309 b->rp = 0; 310 b->rl = min(b->bufsize, rl); 311} 312 313/** 314 * @brief Reset buffer w/o flushing statistics 315 * 316 * This function just zeroes out buffer contents and sets the "ready length" 317 * to zero. This was originally to facilitate minimal playback interruption 318 * (i.e., dropped samples) in SNDCTL_DSP_SILENCE/SKIP ioctls. 319 * 320 * @param b buffer context 321 */ 322void 323sndbuf_softreset(struct snd_dbuf *b) 324{ 325 b->rl = 0; 326 if (b->buf && b->bufsize > 0) 327 sndbuf_clear(b, b->bufsize); 328} 329 330void 331sndbuf_reset(struct snd_dbuf *b) 332{ 333 b->hp = 0; 334 b->rp = 0; 335 b->rl = 0; 336 b->dl = 0; 337 b->prev_total = 0; 338 b->total = 0; 339 b->xrun = 0; 340 if (b->buf && b->bufsize > 0) 341 sndbuf_clear(b, b->bufsize); 342 sndbuf_clearshadow(b); 343} 344 345u_int32_t 346sndbuf_getfmt(struct snd_dbuf *b) 347{ 348 return b->fmt; 349} 350 351int 352sndbuf_setfmt(struct snd_dbuf *b, u_int32_t fmt) 353{ 354 b->fmt = fmt; 355 b->bps = AFMT_BPS(b->fmt); 356 b->align = AFMT_ALIGN(b->fmt); 357#if 0 358 b->bps = AFMT_CHANNEL(b->fmt); 359 if (b->fmt & AFMT_16BIT) 360 b->bps <<= 1; 361 else if (b->fmt & AFMT_24BIT) 362 b->bps *= 3; 363 else if (b->fmt & AFMT_32BIT) 364 b->bps <<= 2; 365#endif 366 return 0; 367} 368 369unsigned int 370sndbuf_getspd(struct snd_dbuf *b) 371{ 372 return b->spd; 373} 374 375void 376sndbuf_setspd(struct snd_dbuf *b, unsigned int spd) 377{ 378 b->spd = spd; 379} 380 381unsigned int 382sndbuf_getalign(struct snd_dbuf *b) 383{ 384 return (b->align); 385} 386 387unsigned int 388sndbuf_getblkcnt(struct snd_dbuf *b) 389{ 390 return b->blkcnt; 391} 392 393void 394sndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt) 395{ 396 b->blkcnt = blkcnt; 397} 398 399unsigned int 400sndbuf_getblksz(struct snd_dbuf *b) 401{ 402 return b->blksz; 403} 404 405void 406sndbuf_setblksz(struct snd_dbuf *b, unsigned int blksz) 407{ 408 b->blksz = blksz; 409} 410 411unsigned int 412sndbuf_getbps(struct snd_dbuf *b) 413{ 414 return b->bps; 415} 416 417void * 418sndbuf_getbuf(struct snd_dbuf *b) 419{ 420 return b->buf; 421} 422 423void * 424sndbuf_getbufofs(struct snd_dbuf *b, unsigned int ofs) 425{ 426 KASSERT(ofs < b->bufsize, ("%s: ofs invalid %d", __func__, ofs)); 427 428 return b->buf + ofs; 429} 430 431unsigned int 432sndbuf_getsize(struct snd_dbuf *b) 433{ 434 return b->bufsize; 435} 436 437unsigned int 438sndbuf_getmaxsize(struct snd_dbuf *b) 439{ 440 return b->maxsize; 441} 442 443unsigned int 444sndbuf_getallocsize(struct snd_dbuf *b) 445{ 446 return b->allocsize; 447} 448 449unsigned int 450sndbuf_runsz(struct snd_dbuf *b) 451{ 452 return b->dl; 453} 454 455void 456sndbuf_setrun(struct snd_dbuf *b, int go) 457{ 458 b->dl = go? b->blksz : 0; 459} 460 461struct selinfo * 462sndbuf_getsel(struct snd_dbuf *b) 463{ 464 return &b->sel; 465} 466 467/************************************************************/ 468unsigned int 469sndbuf_getxrun(struct snd_dbuf *b) 470{ 471 SNDBUF_LOCKASSERT(b); 472 473 return b->xrun; 474} 475 476void 477sndbuf_setxrun(struct snd_dbuf *b, unsigned int xrun) 478{ 479 SNDBUF_LOCKASSERT(b); 480 481 b->xrun = xrun; 482} 483 484unsigned int 485sndbuf_gethwptr(struct snd_dbuf *b) 486{ 487 SNDBUF_LOCKASSERT(b); 488 489 return b->hp; 490} 491 492void 493sndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr) 494{ 495 SNDBUF_LOCKASSERT(b); 496 497 b->hp = ptr; 498} 499 500unsigned int 501sndbuf_getready(struct snd_dbuf *b) 502{ 503 SNDBUF_LOCKASSERT(b); 504 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 505 506 return b->rl; 507} 508 509unsigned int 510sndbuf_getreadyptr(struct snd_dbuf *b) 511{ 512 SNDBUF_LOCKASSERT(b); 513 KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp)); 514 515 return b->rp; 516} 517 518unsigned int 519sndbuf_getfree(struct snd_dbuf *b) 520{ 521 SNDBUF_LOCKASSERT(b); 522 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 523 524 return b->bufsize - b->rl; 525} 526 527unsigned int 528sndbuf_getfreeptr(struct snd_dbuf *b) 529{ 530 SNDBUF_LOCKASSERT(b); 531 KASSERT((b->rp >= 0) && (b->rp <= b->bufsize), ("%s: b->rp invalid %d", __func__, b->rp)); 532 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 533 534 return (b->rp + b->rl) % b->bufsize; 535} 536 537u_int64_t 538sndbuf_getblocks(struct snd_dbuf *b) 539{ 540 SNDBUF_LOCKASSERT(b); 541 542 return b->total / b->blksz; 543} 544 545u_int64_t 546sndbuf_getprevblocks(struct snd_dbuf *b) 547{ 548 SNDBUF_LOCKASSERT(b); 549 550 return b->prev_total / b->blksz; 551} 552 553u_int64_t 554sndbuf_gettotal(struct snd_dbuf *b) 555{ 556 SNDBUF_LOCKASSERT(b); 557 558 return b->total; 559} 560 561u_int64_t 562sndbuf_getprevtotal(struct snd_dbuf *b) 563{ 564 SNDBUF_LOCKASSERT(b); 565 566 return b->prev_total; 567} 568 569void 570sndbuf_updateprevtotal(struct snd_dbuf *b) 571{ 572 SNDBUF_LOCKASSERT(b); 573 574 b->prev_total = b->total; 575} 576 577unsigned int 578sndbuf_xbytes(unsigned int v, struct snd_dbuf *from, struct snd_dbuf *to) 579{ 580 if (from == NULL || to == NULL || v == 0) 581 return 0; 582 583 return snd_xbytes(v, sndbuf_getalign(from) * sndbuf_getspd(from), 584 sndbuf_getalign(to) * sndbuf_getspd(to)); 585} 586 587u_int8_t 588sndbuf_zerodata(u_int32_t fmt) 589{ 590 if (fmt & (AFMT_SIGNED | AFMT_PASSTHROUGH)) 591 return (0x00); 592 else if (fmt & AFMT_MU_LAW) 593 return (0x7f); 594 else if (fmt & AFMT_A_LAW) 595 return (0x55); 596 return (0x80); 597} 598 599/************************************************************/ 600 601/** 602 * @brief Acquire buffer space to extend ready area 603 * 604 * This function extends the ready area length by @c count bytes, and may 605 * optionally copy samples from another location stored in @c from. The 606 * counter @c snd_dbuf::total is also incremented by @c count bytes. 607 * 608 * @param b audio buffer 609 * @param from sample source (optional) 610 * @param count number of bytes to acquire 611 * 612 * @retval 0 Unconditional 613 */ 614int 615sndbuf_acquire(struct snd_dbuf *b, u_int8_t *from, unsigned int count) 616{ 617 int l; 618 619 KASSERT(count <= sndbuf_getfree(b), ("%s: count %d > free %d", __func__, count, sndbuf_getfree(b))); 620 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 621 b->total += count; 622 if (from != NULL) { 623 while (count > 0) { 624 l = min(count, sndbuf_getsize(b) - sndbuf_getfreeptr(b)); 625 bcopy(from, sndbuf_getbufofs(b, sndbuf_getfreeptr(b)), l); 626 from += l; 627 b->rl += l; 628 count -= l; 629 } 630 } else 631 b->rl += count; 632 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count)); 633 634 return 0; 635} 636 637/** 638 * @brief Dispose samples from channel buffer, increasing size of ready area 639 * 640 * This function discards samples from the supplied buffer by advancing the 641 * ready area start pointer and decrementing the ready area length. If 642 * @c to is not NULL, then the discard samples will be copied to the location 643 * it points to. 644 * 645 * @param b PCM channel sound buffer 646 * @param to destination buffer (optional) 647 * @param count number of bytes to discard 648 * 649 * @returns 0 unconditionally 650 */ 651int 652sndbuf_dispose(struct snd_dbuf *b, u_int8_t *to, unsigned int count) 653{ 654 int l; 655 656 KASSERT(count <= sndbuf_getready(b), ("%s: count %d > ready %d", __func__, count, sndbuf_getready(b))); 657 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d", __func__, b->rl)); 658 if (to != NULL) { 659 while (count > 0) { 660 l = min(count, sndbuf_getsize(b) - sndbuf_getreadyptr(b)); 661 bcopy(sndbuf_getbufofs(b, sndbuf_getreadyptr(b)), to, l); 662 to += l; 663 b->rl -= l; 664 b->rp = (b->rp + l) % b->bufsize; 665 count -= l; 666 } 667 } else { 668 b->rl -= count; 669 b->rp = (b->rp + count) % b->bufsize; 670 } 671 KASSERT((b->rl >= 0) && (b->rl <= b->bufsize), ("%s: b->rl invalid %d, count %d", __func__, b->rl, count)); 672 673 return 0; 674} 675 676#ifdef SND_DIAGNOSTIC 677static uint32_t snd_feeder_maxfeed = 0; 678SYSCTL_UINT(_hw_snd, OID_AUTO, feeder_maxfeed, CTLFLAG_RD, 679 &snd_feeder_maxfeed, 0, "maximum feeder count request"); 680 681static uint32_t snd_feeder_maxcycle = 0; 682SYSCTL_UINT(_hw_snd, OID_AUTO, feeder_maxcycle, CTLFLAG_RD, 683 &snd_feeder_maxcycle, 0, "maximum feeder cycle"); 684#endif 685 686/* count is number of bytes we want added to destination buffer */ 687int 688sndbuf_feed(struct snd_dbuf *from, struct snd_dbuf *to, struct pcm_channel *channel, struct pcm_feeder *feeder, unsigned int count) 689{ 690 unsigned int cnt, maxfeed; 691#ifdef SND_DIAGNOSTIC 692 unsigned int cycle; 693 694 if (count > snd_feeder_maxfeed) 695 snd_feeder_maxfeed = count; 696 697 cycle = 0; 698#endif 699 700 KASSERT(count > 0, ("can't feed 0 bytes")); 701 702 if (sndbuf_getfree(to) < count) 703 return (EINVAL); 704 705 maxfeed = SND_FXROUND(SND_FXDIV_MAX, sndbuf_getalign(to)); 706 707 do { 708 cnt = FEEDER_FEED(feeder, channel, to->tmpbuf, 709 min(count, maxfeed), from); 710 if (cnt == 0) 711 break; 712 sndbuf_acquire(to, to->tmpbuf, cnt); 713 count -= cnt; 714#ifdef SND_DIAGNOSTIC 715 cycle++; 716#endif 717 } while (count != 0); 718 719#ifdef SND_DIAGNOSTIC 720 if (cycle > snd_feeder_maxcycle) 721 snd_feeder_maxcycle = cycle; 722#endif 723 724 return (0); 725} 726 727/************************************************************/ 728 729void 730sndbuf_dump(struct snd_dbuf *b, char *s, u_int32_t what) 731{ 732 printf("%s: [", s); 733 if (what & 0x01) 734 printf(" bufsize: %d, maxsize: %d", b->bufsize, b->maxsize); 735 if (what & 0x02) 736 printf(" dl: %d, rp: %d, rl: %d, hp: %d", b->dl, b->rp, b->rl, b->hp); 737 if (what & 0x04) 738 printf(" total: %ju, prev_total: %ju, xrun: %d", (uintmax_t)b->total, (uintmax_t)b->prev_total, b->xrun); 739 if (what & 0x08) 740 printf(" fmt: 0x%x, spd: %d", b->fmt, b->spd); 741 if (what & 0x10) 742 printf(" blksz: %d, blkcnt: %d, flags: 0x%x", b->blksz, b->blkcnt, b->flags); 743 printf(" ]\n"); 744} 745 746/************************************************************/ 747u_int32_t 748sndbuf_getflags(struct snd_dbuf *b) 749{ 750 return b->flags; 751} 752 753void 754sndbuf_setflags(struct snd_dbuf *b, u_int32_t flags, int on) 755{ 756 b->flags &= ~flags; 757 if (on) 758 b->flags |= flags; 759} 760 761/** 762 * @brief Clear the shadow buffer by filling with samples equal to zero. 763 * 764 * @param b buffer to clear 765 */ 766void 767sndbuf_clearshadow(struct snd_dbuf *b) 768{ 769 KASSERT(b != NULL, ("b is a null pointer")); 770 KASSERT(b->sl >= 0, ("illegal shadow length")); 771 772 if ((b->shadbuf != NULL) && (b->sl > 0)) 773 memset(b->shadbuf, sndbuf_zerodata(b->fmt), b->sl); 774} 775 776#ifdef OSSV4_EXPERIMENT 777/** 778 * @brief Return peak value from samples in buffer ready area. 779 * 780 * Peak ranges from 0-32767. If channel is monaural, most significant 16 781 * bits will be zero. For now, only expects to work with 1-2 channel 782 * buffers. 783 * 784 * @note Currently only operates with linear PCM formats. 785 * 786 * @param b buffer to analyze 787 * @param lpeak pointer to store left peak value 788 * @param rpeak pointer to store right peak value 789 */ 790void 791sndbuf_getpeaks(struct snd_dbuf *b, int *lp, int *rp) 792{ 793 u_int32_t lpeak, rpeak; 794 795 lpeak = 0; 796 rpeak = 0; 797 798 /** 799 * @todo fill this in later 800 */ 801} 802#endif 803