mixeng.c 9.9 KB
Newer Older
B
bellard 已提交
1 2 3
/*
 * QEMU Mixing engine
 *
4
 * Copyright (c) 2004-2005 Vassili Karpov (malc)
B
bellard 已提交
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * Copyright (c) 1998 Fabrice Bellard
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
P
Peter Maydell 已提交
25
#include "qemu/osdep.h"
P
pbrook 已提交
26
#include "qemu-common.h"
27
#include "qemu/bswap.h"
28
#include "qemu/error-report.h"
P
pbrook 已提交
29
#include "audio.h"
B
bellard 已提交
30

31 32 33 34 35 36 37 38
#define AUDIO_CAP "mixeng"
#include "audio_int.h"

/* 8 bit */
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)

/* Signed 8 bit */
39 40
#define BSIZE 8
#define ITYPE int
41 42
#define IN_MIN SCHAR_MIN
#define IN_MAX SCHAR_MAX
B
bellard 已提交
43
#define SIGNED
44
#define SHIFT 8
B
bellard 已提交
45 46 47 48
#include "mixeng_template.h"
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
49 50
#undef BSIZE
#undef ITYPE
51
#undef SHIFT
B
bellard 已提交
52

53
/* Unsigned 8 bit */
54 55
#define BSIZE 8
#define ITYPE uint
B
bellard 已提交
56 57
#define IN_MIN 0
#define IN_MAX UCHAR_MAX
58
#define SHIFT 8
B
bellard 已提交
59 60 61
#include "mixeng_template.h"
#undef IN_MAX
#undef IN_MIN
62 63
#undef BSIZE
#undef ITYPE
64 65 66 67
#undef SHIFT

#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
B
bellard 已提交
68

69
/* Signed 16 bit */
70 71
#define BSIZE 16
#define ITYPE int
B
bellard 已提交
72 73 74
#define IN_MIN SHRT_MIN
#define IN_MAX SHRT_MAX
#define SIGNED
75 76 77
#define SHIFT 16
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)
B
bellard 已提交
78
#include "mixeng_template.h"
79 80 81 82 83 84 85
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#define ENDIAN_CONVERSION swap
#define ENDIAN_CONVERT(v) bswap16 (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
B
bellard 已提交
86 87 88
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
89 90
#undef BSIZE
#undef ITYPE
91
#undef SHIFT
B
bellard 已提交
92

93
/* Unsigned 16 bit */
94 95
#define BSIZE 16
#define ITYPE uint
B
bellard 已提交
96 97
#define IN_MIN 0
#define IN_MAX USHRT_MAX
98 99 100 101 102 103 104 105
#define SHIFT 16
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#define ENDIAN_CONVERSION swap
#define ENDIAN_CONVERT(v) bswap16 (v)
B
bellard 已提交
106
#include "mixeng_template.h"
107 108
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
B
bellard 已提交
109 110
#undef IN_MAX
#undef IN_MIN
111 112
#undef BSIZE
#undef ITYPE
113
#undef SHIFT
B
bellard 已提交
114

115
/* Signed 32 bit */
116 117
#define BSIZE 32
#define ITYPE int
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
#define IN_MIN INT32_MIN
#define IN_MAX INT32_MAX
#define SIGNED
#define SHIFT 32
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#define ENDIAN_CONVERSION swap
#define ENDIAN_CONVERT(v) bswap32 (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#undef SIGNED
#undef IN_MAX
#undef IN_MIN
135 136
#undef BSIZE
#undef ITYPE
137 138
#undef SHIFT

M
malc 已提交
139
/* Unsigned 32 bit */
140 141
#define BSIZE 32
#define ITYPE uint
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
#define IN_MIN 0
#define IN_MAX UINT32_MAX
#define SHIFT 32
#define ENDIAN_CONVERSION natural
#define ENDIAN_CONVERT(v) (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#define ENDIAN_CONVERSION swap
#define ENDIAN_CONVERT(v) bswap32 (v)
#include "mixeng_template.h"
#undef ENDIAN_CONVERT
#undef ENDIAN_CONVERSION
#undef IN_MAX
#undef IN_MIN
157 158
#undef BSIZE
#undef ITYPE
159 160 161
#undef SHIFT

t_sample *mixeng_conv[2][2][2][3] = {
B
bellard 已提交
162 163
    {
        {
164 165
            {
                conv_natural_uint8_t_to_mono,
166 167
                conv_natural_uint16_t_to_mono,
                conv_natural_uint32_t_to_mono
168 169 170
            },
            {
                conv_natural_uint8_t_to_mono,
171 172
                conv_swap_uint16_t_to_mono,
                conv_swap_uint32_t_to_mono,
173
            }
B
bellard 已提交
174 175
        },
        {
176 177
            {
                conv_natural_int8_t_to_mono,
178 179
                conv_natural_int16_t_to_mono,
                conv_natural_int32_t_to_mono
180 181 182
            },
            {
                conv_natural_int8_t_to_mono,
183 184
                conv_swap_int16_t_to_mono,
                conv_swap_int32_t_to_mono
185
            }
B
bellard 已提交
186 187 188 189
        }
    },
    {
        {
190 191
            {
                conv_natural_uint8_t_to_stereo,
192 193
                conv_natural_uint16_t_to_stereo,
                conv_natural_uint32_t_to_stereo
194 195 196
            },
            {
                conv_natural_uint8_t_to_stereo,
197 198
                conv_swap_uint16_t_to_stereo,
                conv_swap_uint32_t_to_stereo
199
            }
B
bellard 已提交
200 201
        },
        {
202 203
            {
                conv_natural_int8_t_to_stereo,
204 205
                conv_natural_int16_t_to_stereo,
                conv_natural_int32_t_to_stereo
206 207 208
            },
            {
                conv_natural_int8_t_to_stereo,
209 210
                conv_swap_int16_t_to_stereo,
                conv_swap_int32_t_to_stereo,
211
            }
B
bellard 已提交
212 213 214 215
        }
    }
};

216
f_sample *mixeng_clip[2][2][2][3] = {
B
bellard 已提交
217 218
    {
        {
219 220
            {
                clip_natural_uint8_t_from_mono,
221 222
                clip_natural_uint16_t_from_mono,
                clip_natural_uint32_t_from_mono
223 224 225
            },
            {
                clip_natural_uint8_t_from_mono,
226 227
                clip_swap_uint16_t_from_mono,
                clip_swap_uint32_t_from_mono
228
            }
B
bellard 已提交
229 230
        },
        {
231 232
            {
                clip_natural_int8_t_from_mono,
233 234
                clip_natural_int16_t_from_mono,
                clip_natural_int32_t_from_mono
235 236 237
            },
            {
                clip_natural_int8_t_from_mono,
238 239
                clip_swap_int16_t_from_mono,
                clip_swap_int32_t_from_mono
240
            }
B
bellard 已提交
241 242 243 244
        }
    },
    {
        {
245 246
            {
                clip_natural_uint8_t_from_stereo,
247 248
                clip_natural_uint16_t_from_stereo,
                clip_natural_uint32_t_from_stereo
249 250 251
            },
            {
                clip_natural_uint8_t_from_stereo,
252 253
                clip_swap_uint16_t_from_stereo,
                clip_swap_uint32_t_from_stereo
254
            }
B
bellard 已提交
255 256
        },
        {
257 258
            {
                clip_natural_int8_t_from_stereo,
259 260
                clip_natural_int16_t_from_stereo,
                clip_natural_int32_t_from_stereo
261 262 263
            },
            {
                clip_natural_int8_t_from_stereo,
264 265
                clip_swap_int16_t_from_stereo,
                clip_swap_int32_t_from_stereo
266
            }
B
bellard 已提交
267 268 269 270
        }
    }
};

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301

void audio_sample_to_uint64(void *samples, int pos,
                            uint64_t *left, uint64_t *right)
{
    struct st_sample *sample = samples;
    sample += pos;
#ifdef FLOAT_MIXENG
    error_report(
        "Coreaudio and floating point samples are not supported by replay yet");
    abort();
#else
    *left = sample->l;
    *right = sample->r;
#endif
}

void audio_sample_from_uint64(void *samples, int pos,
                            uint64_t left, uint64_t right)
{
    struct st_sample *sample = samples;
    sample += pos;
#ifdef FLOAT_MIXENG
    error_report(
        "Coreaudio and floating point samples are not supported by replay yet");
    abort();
#else
    sample->l = left;
    sample->r = right;
#endif
}

B
bellard 已提交
302 303 304 305
/*
 * August 21, 1998
 * Copyright 1998 Fabrice Bellard.
 *
S
Stefan Weil 已提交
306
 * [Rewrote completely the code of Lance Norskog And Sundry
B
bellard 已提交
307 308 309
 * Contributors with a more efficient algorithm.]
 *
 * This source code is freely redistributable and may be used for
310 311 312
 * any purpose.  This copyright notice must be maintained.
 * Lance Norskog And Sundry Contributors are not responsible for
 * the consequences of using this software.
B
bellard 已提交
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334
 */

/*
 * Sound Tools rate change effect file.
 */
/*
 * Linear Interpolation.
 *
 * The use of fractional increment allows us to use no buffer. It
 * avoid the problems at the end of the buffer we had with the old
 * method which stored a possibly big buffer of size
 * lcm(in_rate,out_rate).
 *
 * Limited to 16 bit samples and sampling frequency <= 65535 Hz. If
 * the input & output frequencies are equal, a delay of one sample is
 * introduced.  Limited to processing 32-bit count worth of samples.
 *
 * 1 << FRAC_BITS evaluating to zero in several places.  Changed with
 * an (unsigned long) cast to make it safe.  MarkMLl 2/1/99
 */

/* Private data */
B
bellard 已提交
335
struct rate {
B
bellard 已提交
336 337 338
    uint64_t opos;
    uint64_t opos_inc;
    uint32_t ipos;              /* position in the input stream (integer) */
M
malc 已提交
339
    struct st_sample ilast;          /* last sample in the input stream */
B
bellard 已提交
340
};
B
bellard 已提交
341 342 343 344 345 346

/*
 * Prepare processing.
 */
void *st_rate_start (int inrate, int outrate)
{
B
bellard 已提交
347
    struct rate *rate = audio_calloc (AUDIO_FUNC, 1, sizeof (*rate));
B
bellard 已提交
348 349

    if (!rate) {
B
bellard 已提交
350
        dolog ("Could not allocate resampler (%zu bytes)\n", sizeof (*rate));
351
        return NULL;
B
bellard 已提交
352 353 354 355 356
    }

    rate->opos = 0;

    /* increment */
357
    rate->opos_inc = ((uint64_t) inrate << 32) / outrate;
B
bellard 已提交
358 359 360 361 362 363 364

    rate->ipos = 0;
    rate->ilast.l = 0;
    rate->ilast.r = 0;
    return rate;
}

365 366 367
#define NAME st_rate_flow_mix
#define OP(a, b) a += b
#include "rate_template.h"
B
bellard 已提交
368

369 370 371
#define NAME st_rate_flow
#define OP(a, b) a = b
#include "rate_template.h"
B
bellard 已提交
372 373 374

void st_rate_stop (void *opaque)
{
375
    g_free (opaque);
B
bellard 已提交
376
}
377

M
malc 已提交
378
void mixeng_clear (struct st_sample *buf, int len)
379
{
M
malc 已提交
380
    memset (buf, 0, len * sizeof (struct st_sample));
381
}
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

void mixeng_volume (struct st_sample *buf, int len, struct mixeng_volume *vol)
{
    if (vol->mute) {
        mixeng_clear (buf, len);
        return;
    }

    while (len--) {
#ifdef FLOAT_MIXENG
        buf->l = buf->l * vol->l;
        buf->r = buf->r * vol->r;
#else
        buf->l = (buf->l * vol->l) >> 32;
        buf->r = (buf->r * vol->r) >> 32;
#endif
        buf += 1;
    }
}