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/ic/msm6258.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 /*      $NetBSD: msm6258.c,v 1.26 2019/05/08 13:40:18 isaki Exp $       */
    2 
    3 /*
    4  * Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   20  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   22  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   23  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  */
   27 
   28 /*
   29  * OKI MSM6258 ADPCM voice synthesizer codec.
   30  */
   31 
   32 #include <sys/cdefs.h>
   33 __KERNEL_RCSID(0, "$NetBSD: msm6258.c,v 1.26 2019/05/08 13:40:18 isaki Exp $");
   34 
   35 #include <sys/systm.h>
   36 #include <sys/device.h>
   37 #include <sys/kmem.h>
   38 #include <sys/select.h>
   39 #include <sys/audioio.h>
   40 
   41 #include <dev/audio/audio_if.h>
   42 #include <dev/ic/msm6258var.h>
   43 
   44 static inline uint8_t   pcm2adpcm_step(struct msm6258_codecvar *, int16_t);
   45 static inline int16_t   adpcm2pcm_step(struct msm6258_codecvar *, uint8_t);
   46 
   47 static const int adpcm_estimindex[16] = {
   48          2,  6,  10,  14,  18,  22,  26,  30,
   49         -2, -6, -10, -14, -18, -22, -26, -30
   50 };
   51 
   52 static const int adpcm_estim[49] = {
   53          16,  17,  19,  21,  23,  25,  28,  31,  34,  37,
   54          41,  45,  50,  55,  60,  66,  73,  80,  88,  97,
   55         107, 118, 130, 143, 157, 173, 190, 209, 230, 253,
   56         279, 307, 337, 371, 408, 449, 494, 544, 598, 658,
   57         724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
   58 };
   59 
   60 static const int adpcm_estimstep[16] = {
   61         -1, -1, -1, -1, 2, 4, 6, 8,
   62         -1, -1, -1, -1, 2, 4, 6, 8
   63 };
   64 
   65 /*
   66  * signed 16bit linear PCM -> OkiADPCM
   67  */
   68 static inline uint8_t
   69 pcm2adpcm_step(struct msm6258_codecvar *mc, int16_t a)
   70 {
   71         int estim = (int)mc->mc_estim;
   72         int df;
   73         short dl, c;
   74         uint8_t b;
   75         uint8_t s;
   76 
   77         df = a - mc->mc_amp;
   78         dl = adpcm_estim[estim];
   79         c = (df / 16) * 8 / dl;
   80         if (df < 0) {
   81                 b = (unsigned char)(-c) / 2;
   82                 s = 0x08;
   83         } else {
   84                 b = (unsigned char)(c) / 2;
   85                 s = 0;
   86         }
   87         if (b > 7)
   88                 b = 7;
   89         s |= b;
   90         mc->mc_amp += (short)(adpcm_estimindex[(int)s] * dl);
   91         estim += adpcm_estimstep[b];
   92         if (estim < 0)
   93                 estim = 0;
   94         else if (estim > 48)
   95                 estim = 48;
   96 
   97         mc->mc_estim = estim;
   98         return s;
   99 }
  100 
  101 void
  102 msm6258_internal_to_adpcm(audio_filter_arg_t *arg)
  103 {
  104         struct msm6258_codecvar *mc;
  105         const aint_t *src;
  106         uint8_t *dst;
  107         u_int sample_count;
  108         u_int i;
  109 
  110         KASSERT((arg->count & 1) == 0);
  111 
  112         mc = arg->context;
  113         src = arg->src;
  114         dst = arg->dst;
  115         sample_count = arg->count * arg->srcfmt->channels;
  116         for (i = 0; i < sample_count / 2; i++) {
  117                 aint_t s;
  118                 uint8_t f;
  119 
  120                 s = *src++;
  121                 s >>= AUDIO_INTERNAL_BITS - 16;
  122                 f = pcm2adpcm_step(mc, s);
  123 
  124                 s = *src++;
  125                 s >>= AUDIO_INTERNAL_BITS - 16;
  126                 f |= pcm2adpcm_step(mc, s) << 4;
  127 
  128                 *dst++ = (uint8_t)f;
  129         }
  130 }
  131 
  132 
  133 /*
  134  * OkiADPCM -> signed 16bit linear PCM
  135  */
  136 static inline int16_t
  137 adpcm2pcm_step(struct msm6258_codecvar *mc, uint8_t b)
  138 {
  139         int estim = (int)mc->mc_estim;
  140 
  141         mc->mc_amp += adpcm_estim[estim] * adpcm_estimindex[b];
  142         estim += adpcm_estimstep[b];
  143 
  144         if (estim < 0)
  145                 estim = 0;
  146         else if (estim > 48)
  147                 estim = 48;
  148 
  149         mc->mc_estim = estim;
  150 
  151         return mc->mc_amp;
  152 }
  153 
  154 void
  155 msm6258_adpcm_to_internal(audio_filter_arg_t *arg)
  156 {
  157         struct msm6258_codecvar *mc;
  158         const uint8_t *src;
  159         aint_t *dst;
  160         u_int sample_count;
  161         u_int i;
  162 
  163         KASSERT((arg->count & 1) == 0);
  164 
  165         mc = arg->context;
  166         src = arg->src;
  167         dst = arg->dst;
  168         sample_count = arg->count * arg->srcfmt->channels;
  169         for (i = 0; i < sample_count / 2; i++) {
  170                 uint8_t a = *src++;
  171                 aint_t s;
  172 
  173                 s = adpcm2pcm_step(mc, a & 0x0f);
  174                 s <<= AUDIO_INTERNAL_BITS - 16;
  175                 *dst++ = s;
  176 
  177                 s = adpcm2pcm_step(mc, a >> 4);
  178                 s <<= AUDIO_INTERNAL_BITS - 16;
  179                 *dst++ = s;
  180         }
  181 }

Cache object: 3ddf0eb742307dd529cd4fe75dbf75b9


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