xref: /qemu/audio/mixeng_template.h (revision 194bdf50)
185571bc7Sbellard /*
285571bc7Sbellard  * QEMU Mixing engine
385571bc7Sbellard  *
41d14ffa9Sbellard  * Copyright (c) 2004-2005 Vassili Karpov (malc)
585571bc7Sbellard  *
685571bc7Sbellard  * Permission is hereby granted, free of charge, to any person obtaining a copy
785571bc7Sbellard  * of this software and associated documentation files (the "Software"), to deal
885571bc7Sbellard  * in the Software without restriction, including without limitation the rights
985571bc7Sbellard  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1085571bc7Sbellard  * copies of the Software, and to permit persons to whom the Software is
1185571bc7Sbellard  * furnished to do so, subject to the following conditions:
1285571bc7Sbellard  *
1385571bc7Sbellard  * The above copyright notice and this permission notice shall be included in
1485571bc7Sbellard  * all copies or substantial portions of the Software.
1585571bc7Sbellard  *
1685571bc7Sbellard  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1785571bc7Sbellard  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1885571bc7Sbellard  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
1985571bc7Sbellard  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2085571bc7Sbellard  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2185571bc7Sbellard  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2285571bc7Sbellard  * THE SOFTWARE.
2385571bc7Sbellard  */
2485571bc7Sbellard 
2585571bc7Sbellard /*
2685571bc7Sbellard  * Tusen tack till Mike Nordell
2785571bc7Sbellard  * dec++'ified by Dscho
2885571bc7Sbellard  */
2985571bc7Sbellard 
301d14ffa9Sbellard #ifndef SIGNED
311d14ffa9Sbellard #define HALF (IN_MAX >> 1)
3285571bc7Sbellard #endif
3385571bc7Sbellard 
34a2885387SRoger Pau Monne #define ET glue (ENDIAN_CONVERSION, glue (glue (glue (_, ITYPE), BSIZE), _t))
35a2885387SRoger Pau Monne #define IN_T glue (glue (ITYPE, BSIZE), _t)
361d14ffa9Sbellard 
371d14ffa9Sbellard #ifdef FLOAT_MIXENG
glue(conv_,ET)38203cea22SAlex Bligh static inline mixeng_real glue (conv_, ET) (IN_T v)
391d14ffa9Sbellard {
401d14ffa9Sbellard     IN_T nv = ENDIAN_CONVERT (v);
411d14ffa9Sbellard 
421d14ffa9Sbellard #ifdef RECIPROCAL
431d14ffa9Sbellard #ifdef SIGNED
444218fdd7SVolker Rümelin     return nv * (2.f / ((mixeng_real)IN_MAX - IN_MIN));
451d14ffa9Sbellard #else
464218fdd7SVolker Rümelin     return (nv - HALF) * (2.f / (mixeng_real)IN_MAX);
471d14ffa9Sbellard #endif
481d14ffa9Sbellard #else  /* !RECIPROCAL */
491d14ffa9Sbellard #ifdef SIGNED
504218fdd7SVolker Rümelin     return nv / (((mixeng_real)IN_MAX - IN_MIN) / 2.f);
511d14ffa9Sbellard #else
524218fdd7SVolker Rümelin     return (nv - HALF) / ((mixeng_real)IN_MAX / 2.f);
531d14ffa9Sbellard #endif
5485571bc7Sbellard #endif
5585571bc7Sbellard }
5685571bc7Sbellard 
glue(clip_,ET)57203cea22SAlex Bligh static inline IN_T glue (clip_, ET) (mixeng_real v)
5885571bc7Sbellard {
594218fdd7SVolker Rümelin     if (v >= 1.f) {
6085571bc7Sbellard         return IN_MAX;
614218fdd7SVolker Rümelin     } else if (v < -1.f) {
6285571bc7Sbellard         return IN_MIN;
631d14ffa9Sbellard     }
6485571bc7Sbellard 
6585571bc7Sbellard #ifdef SIGNED
664218fdd7SVolker Rümelin     return ENDIAN_CONVERT((IN_T)(v * (((mixeng_real)IN_MAX - IN_MIN) / 2.f)));
6785571bc7Sbellard #else
684218fdd7SVolker Rümelin     return ENDIAN_CONVERT((IN_T)((v * ((mixeng_real)IN_MAX / 2.f)) + HALF));
6985571bc7Sbellard #endif
7085571bc7Sbellard }
7185571bc7Sbellard 
721d14ffa9Sbellard #else  /* !FLOAT_MIXENG */
731d14ffa9Sbellard 
glue(conv_,ET)741d14ffa9Sbellard static inline int64_t glue (conv_, ET) (IN_T v)
7585571bc7Sbellard {
761d14ffa9Sbellard     IN_T nv = ENDIAN_CONVERT (v);
771d14ffa9Sbellard #ifdef SIGNED
781d14ffa9Sbellard     return ((int64_t) nv) << (32 - SHIFT);
791d14ffa9Sbellard #else
801d14ffa9Sbellard     return ((int64_t) nv - HALF) << (32 - SHIFT);
811d14ffa9Sbellard #endif
821d14ffa9Sbellard }
831d14ffa9Sbellard 
glue(clip_,ET)841d14ffa9Sbellard static inline IN_T glue (clip_, ET) (int64_t v)
851d14ffa9Sbellard {
86*194bdf50SVolker Rümelin     if (v >= 0x7fffffffLL) {
871d14ffa9Sbellard         return IN_MAX;
88*194bdf50SVolker Rümelin     } else if (v < -2147483648LL) {
891d14ffa9Sbellard         return IN_MIN;
901d14ffa9Sbellard     }
911d14ffa9Sbellard 
921d14ffa9Sbellard #ifdef SIGNED
931d14ffa9Sbellard     return ENDIAN_CONVERT ((IN_T) (v >> (32 - SHIFT)));
941d14ffa9Sbellard #else
951d14ffa9Sbellard     return ENDIAN_CONVERT ((IN_T) ((v >> (32 - SHIFT)) + HALF));
961d14ffa9Sbellard #endif
971d14ffa9Sbellard }
981d14ffa9Sbellard #endif
991d14ffa9Sbellard 
glue(glue (conv_,ET),_to_stereo)1001d14ffa9Sbellard static void glue (glue (conv_, ET), _to_stereo)
10100e07679SMichael Walle     (struct st_sample *dst, const void *src, int samples)
1021d14ffa9Sbellard {
1031ea879e5Smalc     struct st_sample *out = dst;
10485571bc7Sbellard     IN_T *in = (IN_T *) src;
10500e07679SMichael Walle 
10685571bc7Sbellard     while (samples--) {
10700e07679SMichael Walle         out->l = glue (conv_, ET) (*in++);
10800e07679SMichael Walle         out->r = glue (conv_, ET) (*in++);
10985571bc7Sbellard         out += 1;
11085571bc7Sbellard     }
11185571bc7Sbellard }
11285571bc7Sbellard 
glue(glue (conv_,ET),_to_mono)1131d14ffa9Sbellard static void glue (glue (conv_, ET), _to_mono)
11400e07679SMichael Walle     (struct st_sample *dst, const void *src, int samples)
11585571bc7Sbellard {
1161ea879e5Smalc     struct st_sample *out = dst;
11785571bc7Sbellard     IN_T *in = (IN_T *) src;
11800e07679SMichael Walle 
11985571bc7Sbellard     while (samples--) {
12000e07679SMichael Walle         out->l = glue (conv_, ET) (in[0]);
12185571bc7Sbellard         out->r = out->l;
12285571bc7Sbellard         out += 1;
12385571bc7Sbellard         in += 1;
12485571bc7Sbellard     }
12585571bc7Sbellard }
12685571bc7Sbellard 
glue(glue (clip_,ET),_from_stereo)1271d14ffa9Sbellard static void glue (glue (clip_, ET), _from_stereo)
1281ea879e5Smalc     (void *dst, const struct st_sample *src, int samples)
12985571bc7Sbellard {
1301ea879e5Smalc     const struct st_sample *in = src;
13185571bc7Sbellard     IN_T *out = (IN_T *) dst;
13285571bc7Sbellard     while (samples--) {
1331d14ffa9Sbellard         *out++ = glue (clip_, ET) (in->l);
1341d14ffa9Sbellard         *out++ = glue (clip_, ET) (in->r);
13585571bc7Sbellard         in += 1;
13685571bc7Sbellard     }
13785571bc7Sbellard }
13885571bc7Sbellard 
glue(glue (clip_,ET),_from_mono)1391d14ffa9Sbellard static void glue (glue (clip_, ET), _from_mono)
1401ea879e5Smalc     (void *dst, const struct st_sample *src, int samples)
14185571bc7Sbellard {
1421ea879e5Smalc     const struct st_sample *in = src;
14385571bc7Sbellard     IN_T *out = (IN_T *) dst;
14485571bc7Sbellard     while (samples--) {
1451d14ffa9Sbellard         *out++ = glue (clip_, ET) (in->l + in->r);
14685571bc7Sbellard         in += 1;
14785571bc7Sbellard     }
14885571bc7Sbellard }
14985571bc7Sbellard 
1501d14ffa9Sbellard #undef ET
15185571bc7Sbellard #undef HALF
152a2885387SRoger Pau Monne #undef IN_T
153