Statistics
| Branch: | Revision:

root / audio / mixeng_template.h @ da3d9c5b

History | View | Annotate | Download (4.2 kB)

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
#ifdef CONFIG_MIXEMU
35
#ifdef FLOAT_MIXENG
36
#define VOL(a, b) ((a) * (b))
37
#else
38
#define VOL(a, b) ((a) * (b)) >> 32
39
#endif
40
#else
41
#define VOL(a, b) a
42
#endif
43

    
44
#define ET glue (ENDIAN_CONVERSION, glue (_, IN_T))
45

    
46
#ifdef FLOAT_MIXENG
47
static real_t inline glue (conv_, ET) (IN_T v)
48
{
49
    IN_T nv = ENDIAN_CONVERT (v);
50

    
51
#ifdef RECIPROCAL
52
#ifdef SIGNED
53
    return nv * (1.f / (real_t) (IN_MAX - IN_MIN));
54
#else
55
    return (nv - HALF) * (1.f / (real_t) IN_MAX);
56
#endif
57
#else  /* !RECIPROCAL */
58
#ifdef SIGNED
59
    return nv / (real_t) (IN_MAX - IN_MIN);
60
#else
61
    return (nv - HALF) / (real_t) IN_MAX;
62
#endif
63
#endif
64
}
65

    
66
static IN_T inline glue (clip_, ET) (real_t v)
67
{
68
    if (v >= 0.5) {
69
        return IN_MAX;
70
    }
71
    else if (v < -0.5) {
72
        return IN_MIN;
73
    }
74

    
75
#ifdef SIGNED
76
    return ENDIAN_CONVERT ((IN_T) (v * (IN_MAX - IN_MIN)));
77
#else
78
    return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF));
79
#endif
80
}
81

    
82
#else  /* !FLOAT_MIXENG */
83

    
84
static inline int64_t glue (conv_, ET) (IN_T v)
85
{
86
    IN_T nv = ENDIAN_CONVERT (v);
87
#ifdef SIGNED
88
    return ((int64_t) nv) << (32 - SHIFT);
89
#else
90
    return ((int64_t) nv - HALF) << (32 - SHIFT);
91
#endif
92
}
93

    
94
static inline IN_T glue (clip_, ET) (int64_t v)
95
{
96
    if (v >= 0x7f000000) {
97
        return IN_MAX;
98
    }
99
    else if (v < -2147483648LL) {
100
        return IN_MIN;
101
    }
102

    
103
#ifdef SIGNED
104
    return ENDIAN_CONVERT ((IN_T) (v >> (32 - SHIFT)));
105
#else
106
    return ENDIAN_CONVERT ((IN_T) ((v >> (32 - SHIFT)) + HALF));
107
#endif
108
}
109
#endif
110

    
111
static void glue (glue (conv_, ET), _to_stereo)
112
    (st_sample_t *dst, const void *src, int samples, volume_t *vol)
113
{
114
    st_sample_t *out = dst;
115
    IN_T *in = (IN_T *) src;
116
#ifdef CONFIG_MIXEMU
117
    if (vol->mute) {
118
        mixeng_clear (dst, samples);
119
        return;
120
    }
121
#else
122
    (void) vol;
123
#endif
124
    while (samples--) {
125
        out->l = VOL (glue (conv_, ET) (*in++), vol->l);
126
        out->r = VOL (glue (conv_, ET) (*in++), vol->r);
127
        out += 1;
128
    }
129
}
130

    
131
static void glue (glue (conv_, ET), _to_mono)
132
    (st_sample_t *dst, const void *src, int samples, volume_t *vol)
133
{
134
    st_sample_t *out = dst;
135
    IN_T *in = (IN_T *) src;
136
#ifdef CONFIG_MIXEMU
137
    if (vol->mute) {
138
        mixeng_clear (dst, samples);
139
        return;
140
    }
141
#else
142
    (void) vol;
143
#endif
144
    while (samples--) {
145
        out->l = VOL (glue (conv_, ET) (in[0]), vol->l);
146
        out->r = out->l;
147
        out += 1;
148
        in += 1;
149
    }
150
}
151

    
152
static void glue (glue (clip_, ET), _from_stereo)
153
    (void *dst, const st_sample_t *src, int samples)
154
{
155
    const st_sample_t *in = src;
156
    IN_T *out = (IN_T *) dst;
157
    while (samples--) {
158
        *out++ = glue (clip_, ET) (in->l);
159
        *out++ = glue (clip_, ET) (in->r);
160
        in += 1;
161
    }
162
}
163

    
164
static void glue (glue (clip_, ET), _from_mono)
165
    (void *dst, const st_sample_t *src, int samples)
166
{
167
    const st_sample_t *in = src;
168
    IN_T *out = (IN_T *) dst;
169
    while (samples--) {
170
        *out++ = glue (clip_, ET) (in->l + in->r);
171
        in += 1;
172
    }
173
}
174

    
175
#undef ET
176
#undef HALF
177
#undef VOL