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/feeder_rate.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) 1999 Cameron Grant <gandalf@vilnya.demon.co.uk>
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <dev/sound/pcm/sound.h>
   28 
   29 #include "feeder_if.h"
   30 
   31 SND_DECLARE_FILE("$FreeBSD: releng/5.0/sys/dev/sound/pcm/feeder_rate.c 107237 2002-11-25 17:17:43Z cg $");
   32 
   33 MALLOC_DEFINE(M_RATEFEEDER, "ratefeed", "pcm rate feeder");
   34 
   35 #define FEEDBUFSZ       8192
   36 #undef FEEDER_DEBUG
   37 
   38 struct feed_rate_info {
   39         u_int32_t src, dst;
   40         int srcpos, srcinc;
   41         int16_t *buffer;
   42         u_int16_t alpha;
   43 };
   44 
   45 static int
   46 feed_rate_setup(struct pcm_feeder *f)
   47 {
   48         struct feed_rate_info *info = f->data;
   49 
   50         info->srcinc = (info->src << 16) / info->dst;
   51         /* srcinc is 16.16 fixed point increment for srcpos for each dstpos */
   52         info->srcpos = 0;
   53         return 0;
   54 }
   55 
   56 static int
   57 feed_rate_set(struct pcm_feeder *f, int what, int value)
   58 {
   59         struct feed_rate_info *info = f->data;
   60 
   61         switch(what) {
   62         case FEEDRATE_SRC:
   63                 info->src = value;
   64                 break;
   65         case FEEDRATE_DST:
   66                 info->dst = value;
   67                 break;
   68         default:
   69                 return -1;
   70         }
   71         return feed_rate_setup(f);
   72 }
   73 
   74 static int
   75 feed_rate_get(struct pcm_feeder *f, int what)
   76 {
   77         struct feed_rate_info *info = f->data;
   78 
   79         switch(what) {
   80         case FEEDRATE_SRC:
   81                 return info->src;
   82         case FEEDRATE_DST:
   83                 return info->dst;
   84         default:
   85                 return -1;
   86         }
   87         return -1;
   88 }
   89 
   90 static int
   91 feed_rate_init(struct pcm_feeder *f)
   92 {
   93         struct feed_rate_info *info;
   94 
   95         info = malloc(sizeof(*info), M_RATEFEEDER, M_NOWAIT | M_ZERO);
   96         if (info == NULL)
   97                 return ENOMEM;
   98         info->buffer = malloc(FEEDBUFSZ, M_RATEFEEDER, M_NOWAIT | M_ZERO);
   99         if (info->buffer == NULL) {
  100                 free(info, M_RATEFEEDER);
  101                 return ENOMEM;
  102         }
  103         info->src = DSP_DEFAULT_SPEED;
  104         info->dst = DSP_DEFAULT_SPEED;
  105         info->alpha = 0;
  106         f->data = info;
  107         return feed_rate_setup(f);
  108 }
  109 
  110 static int
  111 feed_rate_free(struct pcm_feeder *f)
  112 {
  113         struct feed_rate_info *info = f->data;
  114 
  115         if (info) {
  116                 if (info->buffer)
  117                         free(info->buffer, M_RATEFEEDER);
  118                 free(info, M_RATEFEEDER);
  119         }
  120         f->data = NULL;
  121         return 0;
  122 }
  123 
  124 static int
  125 feed_rate(struct pcm_feeder *f, struct pcm_channel *c, u_int8_t *b, u_int32_t count, void *source)
  126 {
  127         struct feed_rate_info *info = f->data;
  128         int16_t *destbuf = (int16_t *)b;
  129         int fetch, v, alpha, hidelta, spos, dpos;
  130 
  131         /*
  132          * at this point:
  133          * info->srcpos is 24.8 fixed offset into the fetchbuffer.  0 <= srcpos <= 0xff
  134          *
  135          * our input and output are always AFMT_S16LE stereo.  this simplifies things.
  136          */
  137 
  138         /*
  139          * we start by fetching enough source data into our buffer to generate
  140          * about as much as was requested.  we put it at offset 2 in the
  141          * buffer so that we can interpolate from the last samples in the
  142          * previous iteration- when we finish we will move our last samples
  143          * to the start of the buffer.
  144          */
  145         spos = 0;
  146         dpos = 0;
  147 
  148         /* fetch is in bytes */
  149         fetch = (count * info->srcinc) >> 16;
  150         fetch = min(fetch, FEEDBUFSZ - 4) & ~3;
  151         if (fetch == 0)
  152                 return 0;
  153         fetch = FEEDER_FEED(f->source, c, ((u_int8_t *)info->buffer) + 4, fetch, source);
  154         fetch /= 2;
  155 
  156         alpha = info->alpha;
  157         hidelta = min(info->srcinc >> 16, 1) * 2;
  158         while ((spos + hidelta + 1) < fetch) {
  159                 v = (info->buffer[spos] * (0xffff - alpha)) + (info->buffer[spos + hidelta] * alpha);
  160                 destbuf[dpos++] = v >> 16;
  161 
  162                 v = (info->buffer[spos + 1] * (0xffff - alpha)) + (info->buffer[spos + hidelta + 1] * alpha);
  163                 destbuf[dpos++] = v >> 16;
  164 
  165                 alpha += info->srcinc;
  166                 spos += (alpha >> 16) * 2;
  167                 alpha &= 0xffff;
  168 
  169         }
  170         info->alpha = alpha & 0xffff;
  171         info->buffer[0] = info->buffer[spos - hidelta];
  172         info->buffer[1] = info->buffer[spos - hidelta + 1];
  173 
  174         count = dpos * 2;
  175         return count;
  176 }
  177 
  178 static struct pcm_feederdesc feeder_rate_desc[] = {
  179         {FEEDER_RATE, AFMT_S16_LE | AFMT_STEREO, AFMT_S16_LE | AFMT_STEREO, 0},
  180         {0},
  181 };
  182 static kobj_method_t feeder_rate_methods[] = {
  183         KOBJMETHOD(feeder_init,         feed_rate_init),
  184         KOBJMETHOD(feeder_free,         feed_rate_free),
  185         KOBJMETHOD(feeder_set,          feed_rate_set),
  186         KOBJMETHOD(feeder_get,          feed_rate_get),
  187         KOBJMETHOD(feeder_feed,         feed_rate),
  188         { 0, 0 }
  189 };
  190 FEEDER_DECLARE(feeder_rate, 2, NULL);
  191 
  192 

Cache object: 649ecec01945a71fc8bd55b3b24eafe3


[ 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.