The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/sound/pcm/buffer.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 
   40 SND_DECLARE_FILE("$FreeBSD: releng/10.2/sys/dev/sound/pcm/buffer.c 243450 2012-11-23 13:43:51Z mav $");
   41 
   42 struct snd_dbuf *
   43 sndbuf_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 
   55 void
   56 sndbuf_destroy(struct snd_dbuf *b)
   57 {
   58         sndbuf_free(b);
   59         free(b, M_DEVBUF);
   60 }
   61 
   62 bus_addr_t
   63 sndbuf_getbufaddr(struct snd_dbuf *buf)
   64 {
   65         return (buf->buf_addr);
   66 }
   67 
   68 static void
   69 sndbuf_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 
   89 int
   90 sndbuf_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 
  119 int
  120 sndbuf_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 
  131 void
  132 sndbuf_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 
  160 int
  161 sndbuf_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);
  205 out:
  206         CHN_UNLOCK(b->channel);
  207         return 0;
  208 }
  209 
  210 int
  211 sndbuf_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  */
  266 void
  267 sndbuf_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  */
  295 void
  296 sndbuf_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 
  304 void
  305 sndbuf_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  */
  322 void
  323 sndbuf_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 
  330 void
  331 sndbuf_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 
  345 u_int32_t
  346 sndbuf_getfmt(struct snd_dbuf *b)
  347 {
  348         return b->fmt;
  349 }
  350 
  351 int
  352 sndbuf_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 
  369 unsigned int
  370 sndbuf_getspd(struct snd_dbuf *b)
  371 {
  372         return b->spd;
  373 }
  374 
  375 void
  376 sndbuf_setspd(struct snd_dbuf *b, unsigned int spd)
  377 {
  378         b->spd = spd;
  379 }
  380 
  381 unsigned int
  382 sndbuf_getalign(struct snd_dbuf *b)
  383 {
  384         return (b->align);
  385 }
  386 
  387 unsigned int
  388 sndbuf_getblkcnt(struct snd_dbuf *b)
  389 {
  390         return b->blkcnt;
  391 }
  392 
  393 void
  394 sndbuf_setblkcnt(struct snd_dbuf *b, unsigned int blkcnt)
  395 {
  396         b->blkcnt = blkcnt;
  397 }
  398 
  399 unsigned int
  400 sndbuf_getblksz(struct snd_dbuf *b)
  401 {
  402         return b->blksz;
  403 }
  404 
  405 void
  406 sndbuf_setblksz(struct snd_dbuf *b, unsigned int blksz)
  407 {
  408         b->blksz = blksz;
  409 }
  410 
  411 unsigned int
  412 sndbuf_getbps(struct snd_dbuf *b)
  413 {
  414         return b->bps;
  415 }
  416 
  417 void *
  418 sndbuf_getbuf(struct snd_dbuf *b)
  419 {
  420         return b->buf;
  421 }
  422 
  423 void *
  424 sndbuf_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 
  431 unsigned int
  432 sndbuf_getsize(struct snd_dbuf *b)
  433 {
  434         return b->bufsize;
  435 }
  436 
  437 unsigned int
  438 sndbuf_getmaxsize(struct snd_dbuf *b)
  439 {
  440         return b->maxsize;
  441 }
  442 
  443 unsigned int
  444 sndbuf_getallocsize(struct snd_dbuf *b)
  445 {
  446         return b->allocsize;
  447 }
  448 
  449 unsigned int
  450 sndbuf_runsz(struct snd_dbuf *b)
  451 {
  452         return b->dl;
  453 }
  454 
  455 void
  456 sndbuf_setrun(struct snd_dbuf *b, int go)
  457 {
  458         b->dl = go? b->blksz : 0;
  459 }
  460 
  461 struct selinfo *
  462 sndbuf_getsel(struct snd_dbuf *b)
  463 {
  464         return &b->sel;
  465 }
  466 
  467 /************************************************************/
  468 unsigned int
  469 sndbuf_getxrun(struct snd_dbuf *b)
  470 {
  471         SNDBUF_LOCKASSERT(b);
  472 
  473         return b->xrun;
  474 }
  475 
  476 void
  477 sndbuf_setxrun(struct snd_dbuf *b, unsigned int xrun)
  478 {
  479         SNDBUF_LOCKASSERT(b);
  480 
  481         b->xrun = xrun;
  482 }
  483 
  484 unsigned int
  485 sndbuf_gethwptr(struct snd_dbuf *b)
  486 {
  487         SNDBUF_LOCKASSERT(b);
  488 
  489         return b->hp;
  490 }
  491 
  492 void
  493 sndbuf_sethwptr(struct snd_dbuf *b, unsigned int ptr)
  494 {
  495         SNDBUF_LOCKASSERT(b);
  496 
  497         b->hp = ptr;
  498 }
  499 
  500 unsigned int
  501 sndbuf_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 
  509 unsigned int
  510 sndbuf_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 
  518 unsigned int
  519 sndbuf_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 
  527 unsigned int
  528 sndbuf_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 
  537 u_int64_t
  538 sndbuf_getblocks(struct snd_dbuf *b)
  539 {
  540         SNDBUF_LOCKASSERT(b);
  541 
  542         return b->total / b->blksz;
  543 }
  544 
  545 u_int64_t
  546 sndbuf_getprevblocks(struct snd_dbuf *b)
  547 {
  548         SNDBUF_LOCKASSERT(b);
  549 
  550         return b->prev_total / b->blksz;
  551 }
  552 
  553 u_int64_t
  554 sndbuf_gettotal(struct snd_dbuf *b)
  555 {
  556         SNDBUF_LOCKASSERT(b);
  557 
  558         return b->total;
  559 }
  560 
  561 u_int64_t
  562 sndbuf_getprevtotal(struct snd_dbuf *b)
  563 {
  564         SNDBUF_LOCKASSERT(b);
  565 
  566         return b->prev_total;
  567 }
  568 
  569 void
  570 sndbuf_updateprevtotal(struct snd_dbuf *b)
  571 {
  572         SNDBUF_LOCKASSERT(b);
  573 
  574         b->prev_total = b->total;
  575 }
  576 
  577 unsigned int
  578 sndbuf_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 
  587 u_int8_t
  588 sndbuf_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  */
  614 int
  615 sndbuf_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  */
  651 int
  652 sndbuf_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
  677 static uint32_t snd_feeder_maxfeed = 0;
  678 SYSCTL_UINT(_hw_snd, OID_AUTO, feeder_maxfeed, CTLFLAG_RD,
  679     &snd_feeder_maxfeed, 0, "maximum feeder count request");
  680 
  681 static uint32_t snd_feeder_maxcycle = 0;
  682 SYSCTL_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 */
  687 int
  688 sndbuf_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 
  729 void
  730 sndbuf_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 /************************************************************/
  747 u_int32_t
  748 sndbuf_getflags(struct snd_dbuf *b)
  749 {
  750         return b->flags;
  751 }
  752 
  753 void
  754 sndbuf_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  */
  766 void
  767 sndbuf_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  */
  790 void
  791 sndbuf_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

Cache object: 72313551aaf9f47aa12e77053292531d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.