qemu/audio/mixeng_template.h
<<
>>
Prefs
   1/*
   2 * QEMU Mixing engine
   3 *
   4 * Copyright (c) 2004-2005 Vassili Karpov (malc)
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25/*
  26 * Tusen tack till Mike Nordell
  27 * dec++'ified by Dscho
  28 */
  29
  30#ifndef SIGNED
  31#define HALF (IN_MAX >> 1)
  32#endif
  33
  34#define ET glue (ENDIAN_CONVERSION, glue (glue (glue (_, ITYPE), BSIZE), _t))
  35#define IN_T glue (glue (ITYPE, BSIZE), _t)
  36
  37#ifdef FLOAT_MIXENG
  38static inline mixeng_real glue (conv_, ET) (IN_T v)
  39{
  40    IN_T nv = ENDIAN_CONVERT (v);
  41
  42#ifdef RECIPROCAL
  43#ifdef SIGNED
  44    return nv * (1.f / (mixeng_real) (IN_MAX - IN_MIN));
  45#else
  46    return (nv - HALF) * (1.f / (mixeng_real) IN_MAX);
  47#endif
  48#else  /* !RECIPROCAL */
  49#ifdef SIGNED
  50    return nv / (mixeng_real) ((mixeng_real) IN_MAX - IN_MIN);
  51#else
  52    return (nv - HALF) / (mixeng_real) IN_MAX;
  53#endif
  54#endif
  55}
  56
  57static inline IN_T glue (clip_, ET) (mixeng_real v)
  58{
  59    if (v >= 0.5) {
  60        return IN_MAX;
  61    }
  62    else if (v < -0.5) {
  63        return IN_MIN;
  64    }
  65
  66#ifdef SIGNED
  67    return ENDIAN_CONVERT ((IN_T) (v * ((mixeng_real) IN_MAX - IN_MIN)));
  68#else
  69    return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF));
  70#endif
  71}
  72
  73#else  /* !FLOAT_MIXENG */
  74
  75static inline int64_t glue (conv_, ET) (IN_T v)
  76{
  77    IN_T nv = ENDIAN_CONVERT (v);
  78#ifdef SIGNED
  79    return ((int64_t) nv) << (32 - SHIFT);
  80#else
  81    return ((int64_t) nv - HALF) << (32 - SHIFT);
  82#endif
  83}
  84
  85static inline IN_T glue (clip_, ET) (int64_t v)
  86{
  87    if (v >= 0x7f000000) {
  88        return IN_MAX;
  89    }
  90    else if (v < -2147483648LL) {
  91        return IN_MIN;
  92    }
  93
  94#ifdef SIGNED
  95    return ENDIAN_CONVERT ((IN_T) (v >> (32 - SHIFT)));
  96#else
  97    return ENDIAN_CONVERT ((IN_T) ((v >> (32 - SHIFT)) + HALF));
  98#endif
  99}
 100#endif
 101
 102static void glue (glue (conv_, ET), _to_stereo)
 103    (struct st_sample *dst, const void *src, int samples)
 104{
 105    struct st_sample *out = dst;
 106    IN_T *in = (IN_T *) src;
 107
 108    while (samples--) {
 109        out->l = glue (conv_, ET) (*in++);
 110        out->r = glue (conv_, ET) (*in++);
 111        out += 1;
 112    }
 113}
 114
 115static void glue (glue (conv_, ET), _to_mono)
 116    (struct st_sample *dst, const void *src, int samples)
 117{
 118    struct st_sample *out = dst;
 119    IN_T *in = (IN_T *) src;
 120
 121    while (samples--) {
 122        out->l = glue (conv_, ET) (in[0]);
 123        out->r = out->l;
 124        out += 1;
 125        in += 1;
 126    }
 127}
 128
 129static void glue (glue (clip_, ET), _from_stereo)
 130    (void *dst, const struct st_sample *src, int samples)
 131{
 132    const struct st_sample *in = src;
 133    IN_T *out = (IN_T *) dst;
 134    while (samples--) {
 135        *out++ = glue (clip_, ET) (in->l);
 136        *out++ = glue (clip_, ET) (in->r);
 137        in += 1;
 138    }
 139}
 140
 141static void glue (glue (clip_, ET), _from_mono)
 142    (void *dst, const struct st_sample *src, int samples)
 143{
 144    const struct st_sample *in = src;
 145    IN_T *out = (IN_T *) dst;
 146    while (samples--) {
 147        *out++ = glue (clip_, ET) (in->l + in->r);
 148        in += 1;
 149    }
 150}
 151
 152#undef ET
 153#undef HALF
 154#undef IN_T
 155