VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp@ 90778

Last change on this file since 90778 was 90008, checked in by vboxsync, 3 years ago

AudioMixBuffer: Fixed regresion in AudioMixBufSetVolume from the multichannel volume refactoring. bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 85.4 KB
Line 
1/* $Id: AudioMixBuffer.cpp 90008 2021-07-03 00:02:25Z vboxsync $ */
2/** @file
3 * Audio mixing buffer for converting reading/writing audio data.
4 */
5
6/*
7 * Copyright (C) 2014-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18/** @page pg_audio_mixing_buffers Audio Mixer Buffer
19 *
20 * @section sec_audio_mixing_buffers_volume Soft Volume Control
21 *
22 * The external code supplies an 8-bit volume (attenuation) value in the
23 * 0 .. 255 range. This represents 0 to -96dB attenuation where an input
24 * value of 0 corresponds to -96dB and 255 corresponds to 0dB (unchanged).
25 *
26 * Each step thus corresponds to 96 / 256 or 0.375dB. Every 6dB (16 steps)
27 * represents doubling the sample value.
28 *
29 * For internal use, the volume control needs to be converted to a 16-bit
30 * (sort of) exponential value between 1 and 65536. This is used with fixed
31 * point arithmetic such that 65536 means 1.0 and 1 means 1/65536.
32 *
33 * For actual volume calculation, 33.31 fixed point is used. Maximum (or
34 * unattenuated) volume is represented as 0x40000000; conveniently, this
35 * value fits into a uint32_t.
36 *
37 * To enable fast processing, the maximum volume must be a power of two
38 * and must not have a sign when converted to int32_t. While 0x80000000
39 * violates these constraints, 0x40000000 does not.
40 */
41
42
43/*********************************************************************************************************************************
44* Header Files *
45*********************************************************************************************************************************/
46#define LOG_GROUP LOG_GROUP_AUDIO_MIXER_BUFFER
47#if defined(VBOX_AUDIO_MIX_BUFFER_TESTCASE) && !defined(RT_STRICT)
48# define RT_STRICT /* Run the testcase with assertions because the main functions doesn't return on invalid input. */
49#endif
50#include <VBox/log.h>
51
52#if 0
53/*
54 * AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA enables dumping the raw PCM data
55 * to a file on the host. Be sure to adjust AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH
56 * to your needs before using this!
57 */
58# define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
59# ifdef RT_OS_WINDOWS
60# define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "c:\\temp\\"
61# else
62# define AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "/tmp/"
63# endif
64/* Warning: Enabling this will generate *huge* logs! */
65//# define AUDIOMIXBUF_DEBUG_MACROS
66#endif
67
68#include <iprt/asm-math.h>
69#include <iprt/assert.h>
70#ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA
71# include <iprt/file.h>
72#endif
73#include <iprt/mem.h>
74#include <iprt/string.h> /* For RT_BZERO. */
75
76#ifdef VBOX_AUDIO_TESTCASE
77# define LOG_ENABLED
78# include <iprt/stream.h>
79#endif
80#include <iprt/errcore.h>
81#include <VBox/vmm/pdmaudioinline.h>
82
83#include "AudioMixBuffer.h"
84
85
86/*********************************************************************************************************************************
87* Defined Constants And Macros *
88*********************************************************************************************************************************/
89#ifndef VBOX_AUDIO_TESTCASE
90# ifdef DEBUG
91# define AUDMIXBUF_LOG(x) LogFlowFunc(x)
92# define AUDMIXBUF_LOG_ENABLED
93# else
94# define AUDMIXBUF_LOG(x) do {} while (0)
95# endif
96#else /* VBOX_AUDIO_TESTCASE */
97# define AUDMIXBUF_LOG(x) RTPrintf x
98# define AUDMIXBUF_LOG_ENABLED
99#endif
100
101
102/** Bit shift for fixed point conversion.
103 * @sa @ref sec_audio_mixing_buffers_volume */
104#define AUDIOMIXBUF_VOL_SHIFT 30
105
106/** Internal representation of 0dB volume (1.0 in fixed point).
107 * @sa @ref sec_audio_mixing_buffers_volume */
108#define AUDIOMIXBUF_VOL_0DB (1 << AUDIOMIXBUF_VOL_SHIFT)
109AssertCompile(AUDIOMIXBUF_VOL_0DB <= 0x40000000); /* Must always hold. */
110AssertCompile(AUDIOMIXBUF_VOL_0DB == 0x40000000); /* For now -- when only attenuation is used. */
111
112
113/*********************************************************************************************************************************
114* Global Variables *
115*********************************************************************************************************************************/
116/** Logarithmic/exponential volume conversion table.
117 * @sa @ref sec_audio_mixing_buffers_volume
118 */
119static uint32_t const s_aVolumeConv[256] =
120{
121 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
122 1, 2, 2, 2, 2, 2, 2, 2, /* 15 */
123 2, 2, 2, 2, 2, 3, 3, 3, /* 23 */
124 3, 3, 3, 3, 4, 4, 4, 4, /* 31 */
125 4, 4, 5, 5, 5, 5, 5, 6, /* 39 */
126 6, 6, 6, 7, 7, 7, 8, 8, /* 47 */
127 8, 9, 9, 10, 10, 10, 11, 11, /* 55 */
128 12, 12, 13, 13, 14, 15, 15, 16, /* 63 */
129 17, 17, 18, 19, 20, 21, 22, 23, /* 71 */
130 24, 25, 26, 27, 28, 29, 31, 32, /* 79 */
131 33, 35, 36, 38, 40, 41, 43, 45, /* 87 */
132 47, 49, 52, 54, 56, 59, 61, 64, /* 95 */
133 67, 70, 73, 76, 79, 83, 87, 91, /* 103 */
134 95, 99, 103, 108, 112, 117, 123, 128, /* 111 */
135 134, 140, 146, 152, 159, 166, 173, 181, /* 119 */
136 189, 197, 206, 215, 225, 235, 245, 256, /* 127 */
137 267, 279, 292, 304, 318, 332, 347, 362, /* 135 */
138 378, 395, 412, 431, 450, 470, 490, 512, /* 143 */
139 535, 558, 583, 609, 636, 664, 693, 724, /* 151 */
140 756, 790, 825, 861, 899, 939, 981, 1024, /* 159 */
141 1069, 1117, 1166, 1218, 1272, 1328, 1387, 1448, /* 167 */
142 1512, 1579, 1649, 1722, 1798, 1878, 1961, 2048, /* 175 */
143 2139, 2233, 2332, 2435, 2543, 2656, 2774, 2896, /* 183 */
144 3025, 3158, 3298, 3444, 3597, 3756, 3922, 4096, /* 191 */
145 4277, 4467, 4664, 4871, 5087, 5312, 5547, 5793, /* 199 */
146 6049, 6317, 6597, 6889, 7194, 7512, 7845, 8192, /* 207 */
147 8555, 8933, 9329, 9742, 10173, 10624, 11094, 11585, /* 215 */
148 12098, 12634, 13193, 13777, 14387, 15024, 15689, 16384, /* 223 */
149 17109, 17867, 18658, 19484, 20347, 21247, 22188, 23170, /* 231 */
150 24196, 25268, 26386, 27554, 28774, 30048, 31379, 32768, /* 239 */
151 34219, 35734, 37316, 38968, 40693, 42495, 44376, 46341, /* 247 */
152 48393, 50535, 52773, 55109, 57549, 60097, 62757, 65536, /* 255 */
153};
154
155
156
157#ifdef VBOX_STRICT
158# ifdef UNUSED
159
160/**
161 * Prints a single mixing buffer.
162 * Internal helper function for debugging. Do not use directly.
163 *
164 * @returns VBox status code.
165 * @param pMixBuf Mixing buffer to print.
166 * @param pszFunc Function name to log this for.
167 * @param uIdtLvl Indention level to use.
168 */
169static void audioMixBufDbgPrintSingle(PAUDIOMIXBUF pMixBuf, const char *pszFunc, uint16_t uIdtLvl)
170{
171 Log(("%s: %*s %s: offRead=%RU32, offWrite=%RU32 -> %RU32/%RU32\n",
172 pszFunc, uIdtLvl * 4, "",
173 pMixBuf->pszName, pMixBuf->offRead, pMixBuf->offWrite, pMixBuf->cUsed, pMixBuf->cFrames));
174}
175
176static void audioMixBufDbgPrintInternal(PAUDIOMIXBUF pMixBuf, const char *pszFunc)
177{
178 audioMixBufDbgPrintSingle(pMixBuf, pszFunc, 0 /* iIdtLevel */);
179}
180
181/**
182 * Validates a single mixing buffer.
183 *
184 * @return @true if the buffer state is valid or @false if not.
185 * @param pMixBuf Mixing buffer to validate.
186 */
187static bool audioMixBufDbgValidate(PAUDIOMIXBUF pMixBuf)
188{
189 //const uint32_t offReadEnd = (pMixBuf->offRead + pMixBuf->cUsed) % pMixBuf->cFrames;
190 //const uint32_t offWriteEnd = (pMixBuf->offWrite + (pMixBuf->cFrames - pMixBuf->cUsed)) % pMixBuf->cFrames;
191
192 bool fValid = true;
193
194 AssertStmt(pMixBuf->offRead <= pMixBuf->cFrames, fValid = false);
195 AssertStmt(pMixBuf->offWrite <= pMixBuf->cFrames, fValid = false);
196 AssertStmt(pMixBuf->cUsed <= pMixBuf->cFrames, fValid = false);
197
198 if (pMixBuf->offWrite > pMixBuf->offRead)
199 {
200 if (pMixBuf->offWrite - pMixBuf->offRead != pMixBuf->cUsed)
201 fValid = false;
202 }
203 else if (pMixBuf->offWrite < pMixBuf->offRead)
204 {
205 if (pMixBuf->offWrite + pMixBuf->cFrames - pMixBuf->offRead != pMixBuf->cUsed)
206 fValid = false;
207 }
208
209 if (!fValid)
210 {
211 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);
212 AssertFailed();
213 }
214
215 return fValid;
216}
217
218# endif /* UNUSED */
219#endif /* VBOX_STRICT */
220
221
222/**
223 * Merges @a i32Src into the value stored at @a pi32Dst.
224 *
225 * @param pi32Dst The value to merge @a i32Src into.
226 * @param i32Src The new value to add.
227 */
228DECL_FORCE_INLINE(void) audioMixBufBlendSample(int32_t *pi32Dst, int32_t i32Src)
229{
230 if (i32Src)
231 {
232 int64_t const i32Dst = *pi32Dst;
233 if (!i32Dst)
234 *pi32Dst = i32Src;
235 else
236 *pi32Dst = (int32_t)(((int64_t)i32Dst + i32Src) / 2);
237 }
238}
239
240
241/**
242 * Variant of audioMixBufBlendSample that returns the result rather than storing it.
243 *
244 * This is used for stereo -> mono.
245 */
246DECL_FORCE_INLINE(int32_t) audioMixBufBlendSampleRet(int32_t i32Sample1, int32_t i32Sample2)
247{
248 if (!i32Sample1)
249 return i32Sample2;
250 if (!i32Sample2)
251 return i32Sample1;
252 return (int32_t)(((int64_t)i32Sample1 + i32Sample2) / 2);
253}
254
255
256/**
257 * Blends (merges) the source buffer into the destination buffer.
258 *
259 * We're taking a very simple approach here, working sample by sample:
260 * - if one is silent, use the other one.
261 * - otherwise sum and divide by two.
262 *
263 * @param pi32Dst The destination stream buffer (input and output).
264 * @param pi32Src The source stream buffer.
265 * @param cFrames Number of frames to process.
266 * @param cChannels Number of channels.
267 */
268static void audioMixBufBlendBuffer(int32_t *pi32Dst, int32_t const *pi32Src, uint32_t cFrames, uint8_t cChannels)
269{
270 switch (cChannels)
271 {
272 case 2:
273 while (cFrames-- > 0)
274 {
275 audioMixBufBlendSample(&pi32Dst[0], pi32Src[0]);
276 audioMixBufBlendSample(&pi32Dst[1], pi32Src[1]);
277 pi32Dst += 2;
278 pi32Src += 2;
279 }
280 break;
281
282 default:
283 cFrames *= cChannels;
284 RT_FALL_THROUGH();
285 case 1:
286 while (cFrames-- > 0)
287 {
288 audioMixBufBlendSample(pi32Dst, pi32Src[0]);
289 pi32Dst++;
290 pi32Src++;
291 }
292 break;
293 }
294}
295
296
297#ifdef AUDIOMIXBUF_DEBUG_MACROS
298# define AUDMIXBUF_MACRO_LOG(x) AUDMIXBUF_LOG(x)
299#elif defined(VBOX_AUDIO_TESTCASE_VERBOSE) /* Warning: VBOX_AUDIO_TESTCASE_VERBOSE will generate huge logs! */
300# define AUDMIXBUF_MACRO_LOG(x) RTPrintf x
301#else
302# define AUDMIXBUF_MACRO_LOG(x) do {} while (0)
303#endif
304
305/*
306 * Instantiate format conversion (in and out of the mixer buffer.)
307 */
308/** @todo Currently does not handle any endianness conversion yet! */
309
310/* audioMixBufConvXXXS8: 8-bit, signed. */
311#define a_Name S8
312#define a_Type int8_t
313#define a_Min INT8_MIN
314#define a_Max INT8_MAX
315#define a_fSigned 1
316#define a_cShift 8
317#include "AudioMixBuffer-Convert.cpp.h"
318
319/* audioMixBufConvXXXU8: 8-bit, unsigned. */
320#define a_Name U8
321#define a_Type uint8_t
322#define a_Min 0
323#define a_Max UINT8_MAX
324#define a_fSigned 0
325#define a_cShift 8
326#include "AudioMixBuffer-Convert.cpp.h"
327
328/* audioMixBufConvXXXS16: 16-bit, signed. */
329#define a_Name S16
330#define a_Type int16_t
331#define a_Min INT16_MIN
332#define a_Max INT16_MAX
333#define a_fSigned 1
334#define a_cShift 16
335#include "AudioMixBuffer-Convert.cpp.h"
336
337/* audioMixBufConvXXXU16: 16-bit, unsigned. */
338#define a_Name U16
339#define a_Type uint16_t
340#define a_Min 0
341#define a_Max UINT16_MAX
342#define a_fSigned 0
343#define a_cShift 16
344#include "AudioMixBuffer-Convert.cpp.h"
345
346/* audioMixBufConvXXXS32: 32-bit, signed. */
347#define a_Name S32
348#define a_Type int32_t
349#define a_Min INT32_MIN
350#define a_Max INT32_MAX
351#define a_fSigned 1
352#define a_cShift 32
353#include "AudioMixBuffer-Convert.cpp.h"
354
355/* audioMixBufConvXXXU32: 32-bit, unsigned. */
356#define a_Name U32
357#define a_Type uint32_t
358#define a_Min 0
359#define a_Max UINT32_MAX
360#define a_fSigned 0
361#define a_cShift 32
362#include "AudioMixBuffer-Convert.cpp.h"
363
364/* audioMixBufConvXXXRaw: 32-bit stored as 64-bit, signed. */
365#define a_Name Raw
366#define a_Type int64_t
367#define a_Min INT64_MIN
368#define a_Max INT64_MAX
369#define a_fSigned 1
370#define a_cShift 32 /* Yes, 32! */
371#include "AudioMixBuffer-Convert.cpp.h"
372
373#undef AUDMIXBUF_CONVERT
374#undef AUDMIXBUF_MACRO_LOG
375
376
377/*
378 * Resampling core.
379 */
380/** @todo Separate down- and up-sampling, borrow filter code from RDP. */
381#define COPY_LAST_FRAME_1CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
382 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
383 } while (0)
384#define COPY_LAST_FRAME_2CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
385 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
386 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
387 } while (0)
388#define COPY_LAST_FRAME_3CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
389 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
390 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
391 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
392 } while (0)
393#define COPY_LAST_FRAME_4CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
394 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
395 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
396 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
397 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
398 } while (0)
399#define COPY_LAST_FRAME_5CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
400 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
401 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
402 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
403 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
404 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
405 } while (0)
406#define COPY_LAST_FRAME_6CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
407 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
408 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
409 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
410 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
411 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
412 (a_pi32Dst)[5] = (a_pi32Src)[5]; \
413 } while (0)
414#define COPY_LAST_FRAME_7CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
415 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
416 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
417 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
418 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
419 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
420 (a_pi32Dst)[5] = (a_pi32Src)[5]; \
421 (a_pi32Dst)[6] = (a_pi32Src)[6]; \
422 } while (0)
423#define COPY_LAST_FRAME_8CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
424 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
425 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
426 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
427 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
428 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
429 (a_pi32Dst)[5] = (a_pi32Src)[5]; \
430 (a_pi32Dst)[6] = (a_pi32Src)[6]; \
431 (a_pi32Dst)[7] = (a_pi32Src)[7]; \
432 } while (0)
433#define COPY_LAST_FRAME_9CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
434 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
435 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
436 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
437 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
438 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
439 (a_pi32Dst)[5] = (a_pi32Src)[5]; \
440 (a_pi32Dst)[6] = (a_pi32Src)[6]; \
441 (a_pi32Dst)[7] = (a_pi32Src)[7]; \
442 (a_pi32Dst)[8] = (a_pi32Src)[8]; \
443 } while (0)
444#define COPY_LAST_FRAME_10CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
445 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
446 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
447 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
448 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
449 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
450 (a_pi32Dst)[5] = (a_pi32Src)[5]; \
451 (a_pi32Dst)[6] = (a_pi32Src)[6]; \
452 (a_pi32Dst)[7] = (a_pi32Src)[7]; \
453 (a_pi32Dst)[8] = (a_pi32Src)[8]; \
454 (a_pi32Dst)[9] = (a_pi32Src)[9]; \
455 } while (0)
456#define COPY_LAST_FRAME_11CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
457 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
458 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
459 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
460 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
461 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
462 (a_pi32Dst)[5] = (a_pi32Src)[5]; \
463 (a_pi32Dst)[6] = (a_pi32Src)[6]; \
464 (a_pi32Dst)[7] = (a_pi32Src)[7]; \
465 (a_pi32Dst)[8] = (a_pi32Src)[8]; \
466 (a_pi32Dst)[9] = (a_pi32Src)[9]; \
467 (a_pi32Dst)[10] = (a_pi32Src)[10]; \
468 } while (0)
469#define COPY_LAST_FRAME_12CH(a_pi32Dst, a_pi32Src, a_cChannels) do { \
470 (a_pi32Dst)[0] = (a_pi32Src)[0]; \
471 (a_pi32Dst)[1] = (a_pi32Src)[1]; \
472 (a_pi32Dst)[2] = (a_pi32Src)[2]; \
473 (a_pi32Dst)[3] = (a_pi32Src)[3]; \
474 (a_pi32Dst)[4] = (a_pi32Src)[4]; \
475 (a_pi32Dst)[5] = (a_pi32Src)[5]; \
476 (a_pi32Dst)[6] = (a_pi32Src)[6]; \
477 (a_pi32Dst)[7] = (a_pi32Src)[7]; \
478 (a_pi32Dst)[8] = (a_pi32Src)[8]; \
479 (a_pi32Dst)[9] = (a_pi32Src)[9]; \
480 (a_pi32Dst)[10] = (a_pi32Src)[10]; \
481 (a_pi32Dst)[11] = (a_pi32Src)[11]; \
482 } while (0)
483
484#define INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_iCh) \
485 (a_pi32Dst)[a_iCh] = ((a_pi32Last)[a_iCh] * a_i64FactorLast + (a_pi32Src)[a_iCh] * a_i64FactorCur) >> 32
486#define INTERPOLATE_1CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
487 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
488 } while (0)
489#define INTERPOLATE_2CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
490 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
491 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
492 } while (0)
493#define INTERPOLATE_3CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
494 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
495 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
496 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
497 } while (0)
498#define INTERPOLATE_4CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
499 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
500 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
501 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
502 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
503 } while (0)
504#define INTERPOLATE_5CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
505 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
506 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
507 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
508 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
509 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
510 } while (0)
511#define INTERPOLATE_6CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
512 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
513 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
514 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
515 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
516 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
517 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
518 } while (0)
519#define INTERPOLATE_7CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
520 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
521 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
522 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
523 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
524 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
525 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
526 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
527 } while (0)
528#define INTERPOLATE_8CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
529 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
530 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
531 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
532 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
533 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
534 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
535 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
536 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
537 } while (0)
538#define INTERPOLATE_9CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
539 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
540 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
541 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
542 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
543 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
544 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
545 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
546 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
547 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
548 } while (0)
549#define INTERPOLATE_10CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
550 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
551 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
552 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
553 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
554 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
555 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
556 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
557 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
558 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
559 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 9); \
560 } while (0)
561#define INTERPOLATE_11CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
562 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
563 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
564 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
565 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
566 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
567 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
568 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
569 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
570 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
571 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 9); \
572 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 10); \
573 } while (0)
574#define INTERPOLATE_12CH(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, a_cChannels) do { \
575 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 0); \
576 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 1); \
577 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 2); \
578 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 3); \
579 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 4); \
580 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 5); \
581 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 6); \
582 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 7); \
583 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 8); \
584 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 9); \
585 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 10); \
586 INTERPOLATE_ONE(a_pi32Dst, a_pi32Src, a_pi32Last, a_i64FactorCur, a_i64FactorLast, 11); \
587 } while (0)
588
589#define AUDIOMIXBUF_RESAMPLE(a_cChannels, a_Suffix) \
590 /** @returns Number of destination frames written. */ \
591 static DECLCALLBACK(uint32_t) \
592 audioMixBufResample##a_cChannels##Ch##a_Suffix(int32_t *pi32Dst, uint32_t cDstFrames, \
593 int32_t const *pi32Src, uint32_t cSrcFrames, uint32_t *pcSrcFramesRead, \
594 PAUDIOSTREAMRATE pRate) \
595 { \
596 Log5(("Src: %RU32 L %RU32; Dst: %RU32 L%RU32; uDstInc=%#RX64\n", \
597 pRate->offSrc, cSrcFrames, RT_HI_U32(pRate->offDst), cDstFrames, pRate->uDstInc)); \
598 int32_t * const pi32DstStart = pi32Dst; \
599 int32_t const * const pi32SrcStart = pi32Src; \
600 \
601 int32_t ai32LastFrame[a_cChannels]; \
602 COPY_LAST_FRAME_##a_cChannels##CH(ai32LastFrame, pRate->SrcLast.ai32Samples, a_cChannels); \
603 \
604 while (cDstFrames > 0 && cSrcFrames > 0) \
605 { \
606 int32_t const cSrcNeeded = RT_HI_U32(pRate->offDst) - pRate->offSrc + 1; \
607 if (cSrcNeeded > 0) \
608 { \
609 if ((uint32_t)cSrcNeeded + 1 < cSrcFrames) \
610 { \
611 pRate->offSrc += (uint32_t)cSrcNeeded; \
612 cSrcFrames -= (uint32_t)cSrcNeeded; \
613 pi32Src += (uint32_t)cSrcNeeded * a_cChannels; \
614 COPY_LAST_FRAME_##a_cChannels##CH(ai32LastFrame, &pi32Src[-a_cChannels], a_cChannels); \
615 } \
616 else \
617 { \
618 pi32Src += cSrcFrames * a_cChannels; \
619 pRate->offSrc += cSrcFrames; \
620 COPY_LAST_FRAME_##a_cChannels##CH(pRate->SrcLast.ai32Samples, &pi32Src[-a_cChannels], a_cChannels); \
621 *pcSrcFramesRead = (pi32Src - pi32SrcStart) / a_cChannels; \
622 return (pi32Dst - pi32DstStart) / a_cChannels; \
623 } \
624 } \
625 \
626 /* Interpolate. */ \
627 int64_t const offFactorCur = pRate->offDst & UINT32_MAX; \
628 int64_t const offFactorLast = (int64_t)_4G - offFactorCur; \
629 INTERPOLATE_##a_cChannels##CH(pi32Dst, pi32Src, ai32LastFrame, offFactorCur, offFactorLast, a_cChannels); \
630 \
631 /* Advance. */ \
632 pRate->offDst += pRate->uDstInc; \
633 pi32Dst += a_cChannels; \
634 cDstFrames -= 1; \
635 } \
636 \
637 COPY_LAST_FRAME_##a_cChannels##CH(pRate->SrcLast.ai32Samples, ai32LastFrame, a_cChannels); \
638 *pcSrcFramesRead = (pi32Src - pi32SrcStart) / a_cChannels; \
639 return (pi32Dst - pi32DstStart) / a_cChannels; \
640 }
641
642AUDIOMIXBUF_RESAMPLE(1,Generic)
643AUDIOMIXBUF_RESAMPLE(2,Generic)
644AUDIOMIXBUF_RESAMPLE(3,Generic)
645AUDIOMIXBUF_RESAMPLE(4,Generic)
646AUDIOMIXBUF_RESAMPLE(5,Generic)
647AUDIOMIXBUF_RESAMPLE(6,Generic)
648AUDIOMIXBUF_RESAMPLE(7,Generic)
649AUDIOMIXBUF_RESAMPLE(8,Generic)
650AUDIOMIXBUF_RESAMPLE(9,Generic)
651AUDIOMIXBUF_RESAMPLE(10,Generic)
652AUDIOMIXBUF_RESAMPLE(11,Generic)
653AUDIOMIXBUF_RESAMPLE(12,Generic)
654
655
656/**
657 * Resets the resampling state unconditionally.
658 *
659 * @param pRate The state to reset.
660 */
661static void audioMixBufRateResetAlways(PAUDIOSTREAMRATE pRate)
662{
663 pRate->offDst = 0;
664 pRate->offSrc = 0;
665 for (uintptr_t i = 0; i < RT_ELEMENTS(pRate->SrcLast.ai32Samples); i++)
666 pRate->SrcLast.ai32Samples[0] = 0;
667}
668
669
670/**
671 * Resets the resampling state.
672 *
673 * @param pRate The state to reset.
674 */
675DECLINLINE(void) audioMixBufRateReset(PAUDIOSTREAMRATE pRate)
676{
677 if (pRate->offDst == 0)
678 { /* likely */ }
679 else
680 {
681 Assert(!pRate->fNoConversionNeeded);
682 audioMixBufRateResetAlways(pRate);
683 }
684}
685
686
687/**
688 * Initializes the frame rate converter state.
689 *
690 * @returns VBox status code.
691 * @param pRate The state to initialize.
692 * @param uSrcHz The source frame rate.
693 * @param uDstHz The destination frame rate.
694 * @param cChannels The number of channels in a frame.
695 */
696DECLINLINE(int) audioMixBufRateInit(PAUDIOSTREAMRATE pRate, uint32_t uSrcHz, uint32_t uDstHz, uint8_t cChannels)
697{
698 /*
699 * Do we need to set up frequency conversion?
700 *
701 * Some examples to get an idea of what uDstInc holds:
702 * 44100 to 44100 -> (44100<<32) / 44100 = 0x01'00000000 (4294967296)
703 * 22050 to 44100 -> (22050<<32) / 44100 = 0x00'80000000 (2147483648)
704 * 44100 to 22050 -> (44100<<32) / 22050 = 0x02'00000000 (8589934592)
705 * 44100 to 48000 -> (44100<<32) / 48000 = 0x00'EB333333 (3946001203.2)
706 * 48000 to 44100 -> (48000<<32) / 44100 = 0x01'16A3B35F (4674794335.7823129251700680272109)
707 */
708 audioMixBufRateResetAlways(pRate);
709 if (uSrcHz == uDstHz)
710 {
711 pRate->fNoConversionNeeded = true;
712 pRate->uDstInc = RT_BIT_64(32);
713 pRate->pfnResample = NULL;
714 }
715 else
716 {
717 pRate->fNoConversionNeeded = false;
718 pRate->uDstInc = ((uint64_t)uSrcHz << 32) / uDstHz;
719 AssertReturn(uSrcHz != 0, VERR_INVALID_PARAMETER);
720 switch (cChannels)
721 {
722 case 1: pRate->pfnResample = audioMixBufResample1ChGeneric; break;
723 case 2: pRate->pfnResample = audioMixBufResample2ChGeneric; break;
724 case 3: pRate->pfnResample = audioMixBufResample3ChGeneric; break;
725 case 4: pRate->pfnResample = audioMixBufResample4ChGeneric; break;
726 case 5: pRate->pfnResample = audioMixBufResample5ChGeneric; break;
727 case 6: pRate->pfnResample = audioMixBufResample6ChGeneric; break;
728 case 7: pRate->pfnResample = audioMixBufResample7ChGeneric; break;
729 case 8: pRate->pfnResample = audioMixBufResample8ChGeneric; break;
730 case 9: pRate->pfnResample = audioMixBufResample9ChGeneric; break;
731 case 10: pRate->pfnResample = audioMixBufResample10ChGeneric; break;
732 case 11: pRate->pfnResample = audioMixBufResample11ChGeneric; break;
733 case 12: pRate->pfnResample = audioMixBufResample12ChGeneric; break;
734 default:
735 AssertMsgFailedReturn(("resampling %u changes is not implemented yet\n", cChannels), VERR_OUT_OF_RANGE);
736 }
737 }
738 return VINF_SUCCESS;
739}
740
741
742/**
743 * Initializes a mixing buffer.
744 *
745 * @returns VBox status code.
746 * @param pMixBuf Mixing buffer to initialize.
747 * @param pszName Name of mixing buffer for easier identification. Optional.
748 * @param pProps PCM audio properties to use for the mixing buffer.
749 * @param cFrames Maximum number of audio frames the mixing buffer can hold.
750 */
751int AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
752{
753 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);
754 AssertPtrReturn(pszName, VERR_INVALID_POINTER);
755 AssertPtrReturn(pProps, VERR_INVALID_POINTER);
756 Assert(PDMAudioPropsAreValid(pProps));
757
758 /*
759 * Initialize all members, setting the volume to max (0dB).
760 */
761 pMixBuf->cFrames = 0;
762 pMixBuf->pi32Samples = NULL;
763 pMixBuf->cChannels = 0;
764 pMixBuf->cbFrame = 0;
765 pMixBuf->offRead = 0;
766 pMixBuf->offWrite = 0;
767 pMixBuf->cUsed = 0;
768 pMixBuf->Props = *pProps;
769 pMixBuf->Volume.fMuted = false;
770 pMixBuf->Volume.fAllMax = true;
771 for (uintptr_t i = 0; i < RT_ELEMENTS(pMixBuf->Volume.auChannels); i++)
772 pMixBuf->Volume.auChannels[i] = AUDIOMIXBUF_VOL_0DB;
773
774 int rc;
775 uint8_t const cChannels = PDMAudioPropsChannels(pProps);
776 if (cChannels >= 1 && cChannels <= PDMAUDIO_MAX_CHANNELS)
777 {
778 pMixBuf->pszName = RTStrDup(pszName);
779 if (pMixBuf->pszName)
780 {
781 pMixBuf->pi32Samples = (int32_t *)RTMemAllocZ(cFrames * cChannels * sizeof(pMixBuf->pi32Samples[0]));
782 if (pMixBuf->pi32Samples)
783 {
784 pMixBuf->cFrames = cFrames;
785 pMixBuf->cChannels = cChannels;
786 pMixBuf->cbFrame = cChannels * sizeof(pMixBuf->pi32Samples[0]);
787 pMixBuf->uMagic = AUDIOMIXBUF_MAGIC;
788#ifdef AUDMIXBUF_LOG_ENABLED
789 char szTmp[PDMAUDIOPROPSTOSTRING_MAX];
790 AUDMIXBUF_LOG(("%s: %s - cFrames=%#x (%d)\n",
791 pMixBuf->pszName, PDMAudioPropsToString(pProps, szTmp, sizeof(szTmp)), cFrames, cFrames));
792#endif
793 return VINF_SUCCESS;
794 }
795 RTStrFree(pMixBuf->pszName);
796 pMixBuf->pszName = NULL;
797 rc = VERR_NO_MEMORY;
798 }
799 else
800 rc = VERR_NO_STR_MEMORY;
801 }
802 else
803 {
804 LogRelMaxFunc(64, ("cChannels=%d pszName=%s\n", cChannels, pszName));
805 rc = VERR_OUT_OF_RANGE;
806 }
807 pMixBuf->uMagic = AUDIOMIXBUF_MAGIC_DEAD;
808 return rc;
809}
810
811/**
812 * Terminates (uninitializes) a mixing buffer.
813 *
814 * @param pMixBuf The mixing buffer. Uninitialized mixer buffers will be
815 * quietly ignored. As will NULL.
816 */
817void AudioMixBufTerm(PAUDIOMIXBUF pMixBuf)
818{
819 if (!pMixBuf)
820 return;
821
822 /* Ignore calls for an uninitialized (zeroed) or already destroyed instance. Happens a lot. */
823 if ( pMixBuf->uMagic == 0
824 || pMixBuf->uMagic == AUDIOMIXBUF_MAGIC_DEAD)
825 {
826 Assert(!pMixBuf->pszName);
827 Assert(!pMixBuf->pi32Samples);
828 Assert(!pMixBuf->cFrames);
829 return;
830 }
831
832 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
833 pMixBuf->uMagic = ~AUDIOMIXBUF_MAGIC;
834
835 if (pMixBuf->pszName)
836 {
837 AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName));
838
839 RTStrFree(pMixBuf->pszName);
840 pMixBuf->pszName = NULL;
841 }
842
843 if (pMixBuf->pi32Samples)
844 {
845 Assert(pMixBuf->cFrames);
846 RTMemFree(pMixBuf->pi32Samples);
847 pMixBuf->pi32Samples = NULL;
848 }
849
850 pMixBuf->cFrames = 0;
851 pMixBuf->cChannels = 0;
852}
853
854
855/**
856 * Drops all the frames in the given mixing buffer
857 *
858 * This will reset the read and write offsets to zero.
859 *
860 * @param pMixBuf The mixing buffer. Uninitialized mixer buffers will be
861 * quietly ignored.
862 */
863void AudioMixBufDrop(PAUDIOMIXBUF pMixBuf)
864{
865 AssertPtrReturnVoid(pMixBuf);
866
867 /* Ignore uninitialized (zeroed) mixer sink buffers (happens with AC'97 during VM construction). */
868 if ( pMixBuf->uMagic == 0
869 || pMixBuf->uMagic == AUDIOMIXBUF_MAGIC_DEAD)
870 return;
871
872 AUDMIXBUF_LOG(("%s\n", pMixBuf->pszName));
873
874 pMixBuf->offRead = 0;
875 pMixBuf->offWrite = 0;
876 pMixBuf->cUsed = 0;
877}
878
879
880/**
881 * Gets the maximum number of audio frames this buffer can hold.
882 *
883 * @returns Number of frames.
884 * @param pMixBuf The mixing buffer.
885 */
886uint32_t AudioMixBufSize(PCAUDIOMIXBUF pMixBuf)
887{
888 AssertPtrReturn(pMixBuf, 0);
889 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
890 return pMixBuf->cFrames;
891}
892
893
894/**
895 * Gets the maximum number of bytes this buffer can hold.
896 *
897 * @returns Number of bytes.
898 * @param pMixBuf The mixing buffer.
899 */
900uint32_t AudioMixBufSizeBytes(PCAUDIOMIXBUF pMixBuf)
901{
902 AssertPtrReturn(pMixBuf, 0);
903 AssertReturn(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC, 0);
904 return AUDIOMIXBUF_F2B(pMixBuf, pMixBuf->cFrames);
905}
906
907
908/**
909 * Worker for AudioMixBufUsed and AudioMixBufUsedBytes.
910 */
911DECLINLINE(uint32_t) audioMixBufUsedInternal(PCAUDIOMIXBUF pMixBuf)
912{
913 uint32_t const cFrames = pMixBuf->cFrames;
914 uint32_t cUsed = pMixBuf->cUsed;
915 AssertStmt(cUsed <= cFrames, cUsed = cFrames);
916 return cUsed;
917}
918
919
920/**
921 * Get the number of used (readable) frames in the buffer.
922 *
923 * @returns Number of frames.
924 * @param pMixBuf The mixing buffer.
925 */
926uint32_t AudioMixBufUsed(PCAUDIOMIXBUF pMixBuf)
927{
928 AssertPtrReturn(pMixBuf, 0);
929 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
930 return audioMixBufUsedInternal(pMixBuf);
931}
932
933
934/**
935 * Get the number of (readable) bytes in the buffer.
936 *
937 * @returns Number of bytes.
938 * @param pMixBuf The mixing buffer.
939 */
940uint32_t AudioMixBufUsedBytes(PCAUDIOMIXBUF pMixBuf)
941{
942 AssertPtrReturn(pMixBuf, 0);
943 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
944 return AUDIOMIXBUF_F2B(pMixBuf, audioMixBufUsedInternal(pMixBuf));
945}
946
947
948/**
949 * Worker for AudioMixBufFree and AudioMixBufFreeBytes.
950 */
951DECLINLINE(uint32_t) audioMixBufFreeInternal(PCAUDIOMIXBUF pMixBuf)
952{
953 uint32_t const cFrames = pMixBuf->cFrames;
954 uint32_t cUsed = pMixBuf->cUsed;
955 AssertStmt(cUsed <= cFrames, cUsed = cFrames);
956 uint32_t const cFramesFree = cFrames - cUsed;
957
958 AUDMIXBUF_LOG(("%s: %RU32 of %RU32\n", pMixBuf->pszName, cFramesFree, cFrames));
959 return cFramesFree;
960}
961
962
963/**
964 * Gets the free buffer space in frames.
965 *
966 * @return Number of frames.
967 * @param pMixBuf The mixing buffer.
968 */
969uint32_t AudioMixBufFree(PCAUDIOMIXBUF pMixBuf)
970{
971 AssertPtrReturn(pMixBuf, 0);
972 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
973 return audioMixBufFreeInternal(pMixBuf);
974}
975
976
977/**
978 * Gets the free buffer space in bytes.
979 *
980 * @return Number of bytes.
981 * @param pMixBuf The mixing buffer.
982 */
983uint32_t AudioMixBufFreeBytes(PCAUDIOMIXBUF pMixBuf)
984{
985 AssertPtrReturn(pMixBuf, 0);
986 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
987 return AUDIOMIXBUF_F2B(pMixBuf, audioMixBufFreeInternal(pMixBuf));
988}
989
990
991/**
992 * Checks if the buffer is empty.
993 *
994 * @retval true if empty buffer.
995 * @retval false if not empty and there are frames to be processed.
996 * @param pMixBuf The mixing buffer.
997 */
998bool AudioMixBufIsEmpty(PCAUDIOMIXBUF pMixBuf)
999{
1000 AssertPtrReturn(pMixBuf, true);
1001 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1002 return pMixBuf->cUsed == 0;
1003}
1004
1005
1006/**
1007 * Get the current read position.
1008 *
1009 * This is for the testcase.
1010 *
1011 * @returns Frame number.
1012 * @param pMixBuf The mixing buffer.
1013 */
1014uint32_t AudioMixBufReadPos(PCAUDIOMIXBUF pMixBuf)
1015{
1016 AssertPtrReturn(pMixBuf, 0);
1017 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1018 return pMixBuf->offRead;
1019}
1020
1021
1022/**
1023 * Gets the current write position.
1024 *
1025 * This is for the testcase.
1026 *
1027 * @returns Frame number.
1028 * @param pMixBuf The mixing buffer.
1029 */
1030uint32_t AudioMixBufWritePos(PCAUDIOMIXBUF pMixBuf)
1031{
1032 AssertPtrReturn(pMixBuf, 0);
1033 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1034 return pMixBuf->offWrite;
1035}
1036
1037
1038/**
1039 * Creates a mapping between desination channels and source source channels.
1040 *
1041 * @param paidxChannelMap Where to store the mapping. Indexed by
1042 * destination channel. Entry is either source
1043 * channel index or -1 for zero and -2 for silence.
1044 * @param pSrcProps The source properties.
1045 * @param pDstProps The desination properties.
1046 */
1047static void audioMixBufInitChannelMap(int8_t paidxChannelMap[PDMAUDIO_MAX_CHANNELS],
1048 PCPDMAUDIOPCMPROPS pSrcProps, PCPDMAUDIOPCMPROPS pDstProps)
1049{
1050 uintptr_t const cDstChannels = PDMAudioPropsChannels(pDstProps);
1051 uintptr_t const cSrcChannels = PDMAudioPropsChannels(pSrcProps);
1052 uintptr_t idxDst;
1053 for (idxDst = 0; idxDst < cDstChannels; idxDst++)
1054 {
1055 uint8_t const idDstCh = pDstProps->aidChannels[idxDst];
1056 if (idDstCh >= PDMAUDIOCHANNELID_FRONT_LEFT && idDstCh < PDMAUDIOCHANNELID_END)
1057 {
1058 uintptr_t idxSrc;
1059 for (idxSrc = 0; idxSrc < cSrcChannels; idxSrc++)
1060 if (idDstCh == pSrcProps->aidChannels[idxSrc])
1061 {
1062 paidxChannelMap[idxDst] = idxSrc;
1063 break;
1064 }
1065 if (idxSrc >= cSrcChannels)
1066 {
1067 /** @todo deal with mono. */
1068 paidxChannelMap[idxDst] = -2;
1069 }
1070 }
1071 else if (idDstCh == PDMAUDIOCHANNELID_UNKNOWN)
1072 {
1073 /** @todo What to do here? Pick unused source channels in order? */
1074 paidxChannelMap[idxDst] = -2;
1075 }
1076 else
1077 {
1078 AssertMsg(idDstCh == PDMAUDIOCHANNELID_UNUSED_SILENCE || idDstCh == PDMAUDIOCHANNELID_UNUSED_ZERO,
1079 ("idxDst=%u idDstCh=%u\n", idxDst, idDstCh));
1080 paidxChannelMap[idxDst] = idDstCh == PDMAUDIOCHANNELID_UNUSED_SILENCE ? -2 : -1;
1081 }
1082 }
1083
1084 /* Set the remainder to -1 just to be sure their are safe. */
1085 for (; idxDst < PDMAUDIO_MAX_CHANNELS; idxDst++)
1086 paidxChannelMap[idxDst] = -1;
1087}
1088
1089
1090/**
1091 * Initializes the peek state, setting up encoder and (if necessary) resampling.
1092 *
1093 * @returns VBox status code.
1094 */
1095int AudioMixBufInitPeekState(PCAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFPEEKSTATE pState, PCPDMAUDIOPCMPROPS pProps)
1096{
1097 AssertPtr(pMixBuf);
1098 AssertPtr(pState);
1099 AssertPtr(pProps);
1100
1101 /*
1102 * Pick the encoding function first.
1103 */
1104 uint8_t const cbSample = PDMAudioPropsSampleSize(pProps);
1105 uint8_t const cSrcCh = PDMAudioPropsChannels(&pMixBuf->Props);
1106 uint8_t const cDstCh = PDMAudioPropsChannels(pProps);
1107 pState->cSrcChannels = cSrcCh;
1108 pState->cDstChannels = cDstCh;
1109 pState->cbDstFrame = PDMAudioPropsFrameSize(pProps);
1110 audioMixBufInitChannelMap(pState->aidxChannelMap, &pMixBuf->Props, pProps);
1111 AssertReturn(cDstCh > 0 && cDstCh <= PDMAUDIO_MAX_CHANNELS, VERR_OUT_OF_RANGE);
1112 AssertReturn(cSrcCh > 0 && cSrcCh <= PDMAUDIO_MAX_CHANNELS, VERR_OUT_OF_RANGE);
1113
1114 if (PDMAudioPropsIsSigned(pProps))
1115 {
1116 /* Assign generic encoder first. */
1117 switch (cbSample)
1118 {
1119 case 1: pState->pfnEncode = audioMixBufEncodeGenericS8; break;
1120 case 2: pState->pfnEncode = audioMixBufEncodeGenericS16; break;
1121 case 4: pState->pfnEncode = audioMixBufEncodeGenericS32; break;
1122 case 8:
1123 AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
1124 pState->pfnEncode = audioMixBufEncodeGenericRaw;
1125 break;
1126 default:
1127 AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
1128 }
1129
1130 /* Any specializations available? */
1131 switch (cDstCh)
1132 {
1133 case 1:
1134 if (cSrcCh == 1)
1135 switch (cbSample)
1136 {
1137 case 1: pState->pfnEncode = audioMixBufEncode1ChTo1ChS8; break;
1138 case 2: pState->pfnEncode = audioMixBufEncode1ChTo1ChS16; break;
1139 case 4: pState->pfnEncode = audioMixBufEncode1ChTo1ChS32; break;
1140 case 8: pState->pfnEncode = audioMixBufEncode1ChTo1ChRaw; break;
1141 }
1142 else if (cSrcCh == 2)
1143 switch (cbSample)
1144 {
1145 case 1: pState->pfnEncode = audioMixBufEncode2ChTo1ChS8; break;
1146 case 2: pState->pfnEncode = audioMixBufEncode2ChTo1ChS16; break;
1147 case 4: pState->pfnEncode = audioMixBufEncode2ChTo1ChS32; break;
1148 case 8: pState->pfnEncode = audioMixBufEncode2ChTo1ChRaw; break;
1149 }
1150 break;
1151
1152 case 2:
1153 if (cSrcCh == 1)
1154 switch (cbSample)
1155 {
1156 case 1: pState->pfnEncode = audioMixBufEncode1ChTo2ChS8; break;
1157 case 2: pState->pfnEncode = audioMixBufEncode1ChTo2ChS16; break;
1158 case 4: pState->pfnEncode = audioMixBufEncode1ChTo2ChS32; break;
1159 case 8: pState->pfnEncode = audioMixBufEncode1ChTo2ChRaw; break;
1160 }
1161 else if (cSrcCh == 2)
1162 switch (cbSample)
1163 {
1164 case 1: pState->pfnEncode = audioMixBufEncode2ChTo2ChS8; break;
1165 case 2: pState->pfnEncode = audioMixBufEncode2ChTo2ChS16; break;
1166 case 4: pState->pfnEncode = audioMixBufEncode2ChTo2ChS32; break;
1167 case 8: pState->pfnEncode = audioMixBufEncode2ChTo2ChRaw; break;
1168 }
1169 break;
1170 }
1171 }
1172 else
1173 {
1174 /* Assign generic encoder first. */
1175 switch (cbSample)
1176 {
1177 case 1: pState->pfnEncode = audioMixBufEncodeGenericU8; break;
1178 case 2: pState->pfnEncode = audioMixBufEncodeGenericU16; break;
1179 case 4: pState->pfnEncode = audioMixBufEncodeGenericU32; break;
1180 default:
1181 AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
1182 }
1183
1184 /* Any specializations available? */
1185 switch (cDstCh)
1186 {
1187 case 1:
1188 if (cSrcCh == 1)
1189 switch (cbSample)
1190 {
1191 case 1: pState->pfnEncode = audioMixBufEncode1ChTo1ChU8; break;
1192 case 2: pState->pfnEncode = audioMixBufEncode1ChTo1ChU16; break;
1193 case 4: pState->pfnEncode = audioMixBufEncode1ChTo1ChU32; break;
1194 }
1195 else if (cSrcCh == 2)
1196 switch (cbSample)
1197 {
1198 case 1: pState->pfnEncode = audioMixBufEncode2ChTo1ChU8; break;
1199 case 2: pState->pfnEncode = audioMixBufEncode2ChTo1ChU16; break;
1200 case 4: pState->pfnEncode = audioMixBufEncode2ChTo1ChU32; break;
1201 }
1202 break;
1203
1204 case 2:
1205 if (cSrcCh == 1)
1206 switch (cbSample)
1207 {
1208 case 1: pState->pfnEncode = audioMixBufEncode1ChTo2ChU8; break;
1209 case 2: pState->pfnEncode = audioMixBufEncode1ChTo2ChU16; break;
1210 case 4: pState->pfnEncode = audioMixBufEncode1ChTo2ChU32; break;
1211 }
1212 else if (cSrcCh == 2)
1213 switch (cbSample)
1214 {
1215 case 1: pState->pfnEncode = audioMixBufEncode2ChTo2ChU8; break;
1216 case 2: pState->pfnEncode = audioMixBufEncode2ChTo2ChU16; break;
1217 case 4: pState->pfnEncode = audioMixBufEncode2ChTo2ChU32; break;
1218 }
1219 break;
1220 }
1221 }
1222
1223 int rc = audioMixBufRateInit(&pState->Rate, PDMAudioPropsHz(&pMixBuf->Props), PDMAudioPropsHz(pProps), cSrcCh);
1224 AUDMIXBUF_LOG(("%s: %RU32 Hz to %RU32 Hz => uDstInc=0x%'RX64\n", pMixBuf->pszName, PDMAudioPropsHz(&pMixBuf->Props),
1225 PDMAudioPropsHz(pProps), pState->Rate.uDstInc));
1226 return rc;
1227}
1228
1229
1230/**
1231 * Initializes the write/blend state, setting up decoders and (if necessary)
1232 * resampling.
1233 *
1234 * @returns VBox status code.
1235 */
1236int AudioMixBufInitWriteState(PCAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, PCPDMAUDIOPCMPROPS pProps)
1237{
1238 AssertPtr(pMixBuf);
1239 AssertPtr(pState);
1240 AssertPtr(pProps);
1241
1242 /*
1243 * Pick the encoding function first.
1244 */
1245 uint8_t const cbSample = PDMAudioPropsSampleSize(pProps);
1246 uint8_t const cSrcCh = PDMAudioPropsChannels(pProps);
1247 uint8_t const cDstCh = PDMAudioPropsChannels(&pMixBuf->Props);
1248 pState->cSrcChannels = cSrcCh;
1249 pState->cDstChannels = cDstCh;
1250 pState->cbSrcFrame = PDMAudioPropsFrameSize(pProps);
1251 audioMixBufInitChannelMap(pState->aidxChannelMap, pProps, &pMixBuf->Props);
1252
1253 if (PDMAudioPropsIsSigned(pProps))
1254 {
1255 /* Assign generic decoders first. */
1256 switch (cbSample)
1257 {
1258 case 1:
1259 pState->pfnDecode = audioMixBufDecodeGenericS8;
1260 pState->pfnDecodeBlend = audioMixBufDecodeGenericS8Blend;
1261 break;
1262 case 2:
1263 pState->pfnDecode = audioMixBufDecodeGenericS16;
1264 pState->pfnDecodeBlend = audioMixBufDecodeGenericS16Blend;
1265 break;
1266 case 4:
1267 pState->pfnDecode = audioMixBufDecodeGenericS32;
1268 pState->pfnDecodeBlend = audioMixBufDecodeGenericS32Blend;
1269 break;
1270 case 8:
1271 AssertReturn(pProps->fRaw, VERR_DISK_INVALID_FORMAT);
1272 pState->pfnDecode = audioMixBufDecodeGenericRaw;
1273 pState->pfnDecodeBlend = audioMixBufDecodeGenericRawBlend;
1274 break;
1275 default:
1276 AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
1277 }
1278
1279 /* Any specializations available? */
1280 switch (cDstCh)
1281 {
1282 case 1:
1283 if (cSrcCh == 1)
1284 switch (cbSample)
1285 {
1286 case 1:
1287 pState->pfnDecode = audioMixBufDecode1ChTo1ChS8;
1288 pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChS8Blend;
1289 break;
1290 case 2:
1291 pState->pfnDecode = audioMixBufDecode1ChTo1ChS16;
1292 pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChS16Blend;
1293 break;
1294 case 4:
1295 pState->pfnDecode = audioMixBufDecode1ChTo1ChS32;
1296 pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChS32Blend;
1297 break;
1298 case 8:
1299 pState->pfnDecode = audioMixBufDecode1ChTo1ChRaw;
1300 pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChRawBlend;
1301 break;
1302 }
1303 else if (cSrcCh == 2)
1304 switch (cbSample)
1305 {
1306 case 1:
1307 pState->pfnDecode = audioMixBufDecode2ChTo1ChS8;
1308 pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChS8Blend;
1309 break;
1310 case 2:
1311 pState->pfnDecode = audioMixBufDecode2ChTo1ChS16;
1312 pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChS16Blend;
1313 break;
1314 case 4:
1315 pState->pfnDecode = audioMixBufDecode2ChTo1ChS32;
1316 pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChS32Blend;
1317 break;
1318 case 8:
1319 pState->pfnDecode = audioMixBufDecode2ChTo1ChRaw;
1320 pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChRawBlend;
1321 break;
1322 }
1323 break;
1324
1325 case 2:
1326 if (cSrcCh == 1)
1327 switch (cbSample)
1328 {
1329 case 1:
1330 pState->pfnDecode = audioMixBufDecode1ChTo2ChS8;
1331 pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChS8Blend;
1332 break;
1333 case 2:
1334 pState->pfnDecode = audioMixBufDecode1ChTo2ChS16;
1335 pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChS16Blend;
1336 break;
1337 case 4:
1338 pState->pfnDecode = audioMixBufDecode1ChTo2ChS32;
1339 pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChS32Blend;
1340 break;
1341 case 8:
1342 pState->pfnDecode = audioMixBufDecode1ChTo2ChRaw;
1343 pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChRawBlend;
1344 break;
1345 }
1346 else if (cSrcCh == 2)
1347 switch (cbSample)
1348 {
1349 case 1:
1350 pState->pfnDecode = audioMixBufDecode2ChTo2ChS8;
1351 pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChS8Blend;
1352 break;
1353 case 2:
1354 pState->pfnDecode = audioMixBufDecode2ChTo2ChS16;
1355 pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChS16Blend;
1356 break;
1357 case 4:
1358 pState->pfnDecode = audioMixBufDecode2ChTo2ChS32;
1359 pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChS32Blend;
1360 break;
1361 case 8:
1362 pState->pfnDecode = audioMixBufDecode2ChTo2ChRaw;
1363 pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChRawBlend;
1364 break;
1365 }
1366 break;
1367 }
1368 }
1369 else
1370 {
1371 /* Assign generic decoders first. */
1372 switch (cbSample)
1373 {
1374 case 1:
1375 pState->pfnDecode = audioMixBufDecodeGenericU8;
1376 pState->pfnDecodeBlend = audioMixBufDecodeGenericU8Blend;
1377 break;
1378 case 2:
1379 pState->pfnDecode = audioMixBufDecodeGenericU16;
1380 pState->pfnDecodeBlend = audioMixBufDecodeGenericU16Blend;
1381 break;
1382 case 4:
1383 pState->pfnDecode = audioMixBufDecodeGenericU32;
1384 pState->pfnDecodeBlend = audioMixBufDecodeGenericU32Blend;
1385 break;
1386 default:
1387 AssertMsgFailedReturn(("%u bytes\n", cbSample), VERR_OUT_OF_RANGE);
1388 }
1389
1390 /* Any specializations available? */
1391 switch (cDstCh)
1392 {
1393 case 1:
1394 if (cSrcCh == 1)
1395 switch (cbSample)
1396 {
1397 case 1:
1398 pState->pfnDecode = audioMixBufDecode1ChTo1ChU8;
1399 pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChU8Blend;
1400 break;
1401 case 2:
1402 pState->pfnDecode = audioMixBufDecode1ChTo1ChU16;
1403 pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChU16Blend;
1404 break;
1405 case 4:
1406 pState->pfnDecode = audioMixBufDecode1ChTo1ChU32;
1407 pState->pfnDecodeBlend = audioMixBufDecode1ChTo1ChU32Blend;
1408 break;
1409 }
1410 else if (cSrcCh == 2)
1411 switch (cbSample)
1412 {
1413 case 1:
1414 pState->pfnDecode = audioMixBufDecode2ChTo1ChU8;
1415 pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChU8Blend;
1416 break;
1417 case 2:
1418 pState->pfnDecode = audioMixBufDecode2ChTo1ChU16;
1419 pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChU16Blend;
1420 break;
1421 case 4:
1422 pState->pfnDecode = audioMixBufDecode2ChTo1ChU32;
1423 pState->pfnDecodeBlend = audioMixBufDecode2ChTo1ChU32Blend;
1424 break;
1425 }
1426 break;
1427
1428 case 2:
1429 if (cSrcCh == 1)
1430 switch (cbSample)
1431 {
1432 case 1:
1433 pState->pfnDecode = audioMixBufDecode1ChTo2ChU8;
1434 pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChU8Blend;
1435 break;
1436 case 2:
1437 pState->pfnDecode = audioMixBufDecode1ChTo2ChU16;
1438 pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChU16Blend;
1439 break;
1440 case 4:
1441 pState->pfnDecode = audioMixBufDecode1ChTo2ChU32;
1442 pState->pfnDecodeBlend = audioMixBufDecode1ChTo2ChU32Blend;
1443 break;
1444 }
1445 else if (cSrcCh == 2)
1446 switch (cbSample)
1447 {
1448 case 1:
1449 pState->pfnDecode = audioMixBufDecode2ChTo2ChU8;
1450 pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChU8Blend;
1451 break;
1452 case 2:
1453 pState->pfnDecode = audioMixBufDecode2ChTo2ChU16;
1454 pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChU16Blend;
1455 break;
1456 case 4:
1457 pState->pfnDecode = audioMixBufDecode2ChTo2ChU32;
1458 pState->pfnDecodeBlend = audioMixBufDecode2ChTo2ChU32Blend;
1459 break;
1460 }
1461 break;
1462 }
1463 }
1464
1465 int rc = audioMixBufRateInit(&pState->Rate, PDMAudioPropsHz(pProps), PDMAudioPropsHz(&pMixBuf->Props), cDstCh);
1466 AUDMIXBUF_LOG(("%s: %RU32 Hz to %RU32 Hz => uDstInc=0x%'RX64\n", pMixBuf->pszName, PDMAudioPropsHz(pProps),
1467 PDMAudioPropsHz(&pMixBuf->Props), pState->Rate.uDstInc));
1468 return rc;
1469}
1470
1471
1472/**
1473 * Worker for AudioMixBufPeek that handles the rate conversion case.
1474 */
1475DECL_NO_INLINE(static, void)
1476audioMixBufPeekResampling(PCAUDIOMIXBUF pMixBuf, uint32_t offSrcFrame, uint32_t cMaxSrcFrames, uint32_t *pcSrcFramesPeeked,
1477 PAUDIOMIXBUFPEEKSTATE pState, void *pvDst, uint32_t cbDst, uint32_t *pcbDstPeeked)
1478{
1479 *pcSrcFramesPeeked = 0;
1480 *pcbDstPeeked = 0;
1481 while (cMaxSrcFrames > 0 && cbDst >= pState->cbDstFrame)
1482 {
1483 /* Rate conversion into temporary buffer. */
1484 int32_t ai32DstRate[1024];
1485 uint32_t cSrcFrames = RT_MIN(pMixBuf->cFrames - offSrcFrame, cMaxSrcFrames);
1486 uint32_t cDstMaxFrames = RT_MIN(RT_ELEMENTS(ai32DstRate) / pState->cSrcChannels, cbDst / pState->cbDstFrame);
1487 uint32_t const cDstFrames = pState->Rate.pfnResample(ai32DstRate, cDstMaxFrames,
1488 &pMixBuf->pi32Samples[offSrcFrame * pMixBuf->cChannels],
1489 cSrcFrames, &cSrcFrames, &pState->Rate);
1490 *pcSrcFramesPeeked += cSrcFrames;
1491 cMaxSrcFrames -= cSrcFrames;
1492 offSrcFrame = (offSrcFrame + cSrcFrames) % pMixBuf->cFrames;
1493
1494 /* Encode the converted frames. */
1495 uint32_t const cbDstEncoded = cDstFrames * pState->cbDstFrame;
1496 pState->pfnEncode(pvDst, ai32DstRate, cDstFrames, pState);
1497 *pcbDstPeeked += cbDstEncoded;
1498 cbDst -= cbDstEncoded;
1499 pvDst = (uint8_t *)pvDst + cbDstEncoded;
1500 }
1501}
1502
1503
1504/**
1505 * Copies data out of the mixing buffer, converting it if needed, but leaves the
1506 * read offset untouched.
1507 *
1508 * @param pMixBuf The mixing buffer.
1509 * @param offSrcFrame The offset to start reading at relative to
1510 * current read position (offRead). The caller has
1511 * made sure there is at least this number of
1512 * frames available in the buffer before calling.
1513 * @param cMaxSrcFrames Maximum number of frames to read.
1514 * @param pcSrcFramesPeeked Where to return the actual number of frames read
1515 * from the mixing buffer.
1516 * @param pState Output configuration & conversion state.
1517 * @param pvDst The destination buffer.
1518 * @param cbDst The size of the destination buffer in bytes.
1519 * @param pcbDstPeeked Where to put the actual number of bytes
1520 * returned.
1521 */
1522void AudioMixBufPeek(PCAUDIOMIXBUF pMixBuf, uint32_t offSrcFrame, uint32_t cMaxSrcFrames, uint32_t *pcSrcFramesPeeked,
1523 PAUDIOMIXBUFPEEKSTATE pState, void *pvDst, uint32_t cbDst, uint32_t *pcbDstPeeked)
1524{
1525 /*
1526 * Check inputs.
1527 */
1528 AssertPtr(pMixBuf);
1529 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1530 AssertPtr(pState);
1531 AssertPtr(pState->pfnEncode);
1532 Assert(pState->cSrcChannels == PDMAudioPropsChannels(&pMixBuf->Props));
1533 Assert(cMaxSrcFrames > 0);
1534 Assert(cMaxSrcFrames <= pMixBuf->cFrames);
1535 Assert(offSrcFrame <= pMixBuf->cFrames);
1536 Assert(offSrcFrame + cMaxSrcFrames <= pMixBuf->cUsed);
1537 AssertPtr(pcSrcFramesPeeked);
1538 AssertPtr(pvDst);
1539 Assert(cbDst >= pState->cbDstFrame);
1540 AssertPtr(pcbDstPeeked);
1541
1542 /*
1543 * Make start frame absolute.
1544 */
1545 offSrcFrame = (pMixBuf->offRead + offSrcFrame) % pMixBuf->cFrames;
1546
1547 /*
1548 * Hopefully no sample rate conversion is necessary...
1549 */
1550 if (pState->Rate.fNoConversionNeeded)
1551 {
1552 /* Figure out how much we should convert. */
1553 cMaxSrcFrames = RT_MIN(cMaxSrcFrames, cbDst / pState->cbDstFrame);
1554 *pcSrcFramesPeeked = cMaxSrcFrames;
1555 *pcbDstPeeked = cMaxSrcFrames * pState->cbDstFrame;
1556
1557 /* First chunk. */
1558 uint32_t const cSrcFrames1 = RT_MIN(pMixBuf->cFrames - offSrcFrame, cMaxSrcFrames);
1559 pState->pfnEncode(pvDst, &pMixBuf->pi32Samples[offSrcFrame * pMixBuf->cChannels], cSrcFrames1, pState);
1560
1561 /* Another chunk from the start of the mixing buffer? */
1562 if (cMaxSrcFrames > cSrcFrames1)
1563 pState->pfnEncode((uint8_t *)pvDst + cSrcFrames1 * pState->cbDstFrame,
1564 &pMixBuf->pi32Samples[0], cMaxSrcFrames - cSrcFrames1, pState);
1565
1566 //Log9Func(("*pcbDstPeeked=%#x\n%32.*Rhxd\n", *pcbDstPeeked, *pcbDstPeeked, pvDst));
1567 }
1568 else
1569 audioMixBufPeekResampling(pMixBuf, offSrcFrame, cMaxSrcFrames, pcSrcFramesPeeked, pState, pvDst, cbDst, pcbDstPeeked);
1570}
1571
1572
1573/**
1574 * Worker for AudioMixBufWrite that handles the rate conversion case.
1575 */
1576DECL_NO_INLINE(static, void)
1577audioMixBufWriteResampling(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
1578 uint32_t offDstFrame, uint32_t cDstMaxFrames, uint32_t *pcDstFramesWritten)
1579{
1580 *pcDstFramesWritten = 0;
1581 while (cDstMaxFrames > 0 && cbSrcBuf >= pState->cbSrcFrame)
1582 {
1583 /* Decode into temporary buffer. */
1584 int32_t ai32Decoded[1024];
1585 uint32_t cFramesDecoded = RT_MIN(RT_ELEMENTS(ai32Decoded) / pState->cDstChannels, cbSrcBuf / pState->cbSrcFrame);
1586 pState->pfnDecode(ai32Decoded, pvSrcBuf, cFramesDecoded, pState);
1587 cbSrcBuf -= cFramesDecoded * pState->cbSrcFrame;
1588 pvSrcBuf = (uint8_t const *)pvSrcBuf + cFramesDecoded * pState->cbSrcFrame;
1589
1590 /* Rate convert that into the mixer. */
1591 uint32_t iFrameDecoded = 0;
1592 while (iFrameDecoded < cFramesDecoded)
1593 {
1594 uint32_t cDstMaxFramesNow = RT_MIN(pMixBuf->cFrames - offDstFrame, cDstMaxFrames);
1595 uint32_t cSrcFrames = cFramesDecoded - iFrameDecoded;
1596 uint32_t const cDstFrames = pState->Rate.pfnResample(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels],
1597 cDstMaxFramesNow,
1598 &ai32Decoded[iFrameDecoded * pState->cDstChannels],
1599 cSrcFrames, &cSrcFrames, &pState->Rate);
1600
1601 iFrameDecoded += cSrcFrames;
1602 *pcDstFramesWritten += cDstFrames;
1603 offDstFrame = (offDstFrame + cDstFrames) % pMixBuf->cFrames;
1604 }
1605 }
1606
1607 /** @todo How to squeeze odd frames out of 22050 => 44100 conversion? */
1608}
1609
1610
1611/**
1612 * Writes @a cbSrcBuf bytes to the mixer buffer starting at @a offDstFrame,
1613 * converting it as needed, leaving the write offset untouched.
1614 *
1615 * @param pMixBuf The mixing buffer.
1616 * @param pState Source configuration & conversion state.
1617 * @param pvSrcBuf The source frames.
1618 * @param cbSrcBuf Number of bytes of source frames. This will be
1619 * convered in full.
1620 * @param offDstFrame Mixing buffer offset relative to the write
1621 * position.
1622 * @param cDstMaxFrames Max number of frames to write.
1623 * @param pcDstFramesWritten Where to return the number of frames actually
1624 * written.
1625 *
1626 * @note Does not advance the write position, please call AudioMixBufCommit()
1627 * to do that.
1628 */
1629void AudioMixBufWrite(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
1630 uint32_t offDstFrame, uint32_t cDstMaxFrames, uint32_t *pcDstFramesWritten)
1631{
1632 /*
1633 * Check inputs.
1634 */
1635 AssertPtr(pMixBuf);
1636 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1637 AssertPtr(pState);
1638 AssertPtr(pState->pfnDecode);
1639 AssertPtr(pState->pfnDecodeBlend);
1640 Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
1641 Assert(cDstMaxFrames > 0);
1642 Assert(cDstMaxFrames <= pMixBuf->cFrames - pMixBuf->cUsed);
1643 Assert(offDstFrame <= pMixBuf->cFrames);
1644 AssertPtr(pvSrcBuf);
1645 Assert(!(cbSrcBuf % pState->cbSrcFrame));
1646 AssertPtr(pcDstFramesWritten);
1647
1648 /*
1649 * Make start frame absolute.
1650 */
1651 offDstFrame = (pMixBuf->offWrite + offDstFrame) % pMixBuf->cFrames;
1652
1653 /*
1654 * Hopefully no sample rate conversion is necessary...
1655 */
1656 if (pState->Rate.fNoConversionNeeded)
1657 {
1658 /* Figure out how much we should convert. */
1659 Assert(cDstMaxFrames >= cbSrcBuf / pState->cbSrcFrame);
1660 cDstMaxFrames = RT_MIN(cDstMaxFrames, cbSrcBuf / pState->cbSrcFrame);
1661 *pcDstFramesWritten = cDstMaxFrames;
1662
1663 //Log10Func(("cbSrc=%#x\n%32.*Rhxd\n", pState->cbSrcFrame * cDstMaxFrames, pState->cbSrcFrame * cDstMaxFrames, pvSrcBuf));
1664
1665 /* First chunk. */
1666 uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cDstMaxFrames);
1667 pState->pfnDecode(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels], pvSrcBuf, cDstFrames1, pState);
1668 //Log8Func(("offDstFrame=%#x cDstFrames1=%#x\n%32.*Rhxd\n", offDstFrame, cDstFrames1,
1669 // cDstFrames1 * pMixBuf->cbFrame, &pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels]));
1670
1671 /* Another chunk from the start of the mixing buffer? */
1672 if (cDstMaxFrames > cDstFrames1)
1673 {
1674 pState->pfnDecode(&pMixBuf->pi32Samples[0], (uint8_t *)pvSrcBuf + cDstFrames1 * pState->cbSrcFrame,
1675 cDstMaxFrames - cDstFrames1, pState);
1676 //Log8Func(("cDstFrames2=%#x\n%32.*Rhxd\n", cDstMaxFrames - cDstFrames1,
1677 // (cDstMaxFrames - cDstFrames1) * pMixBuf->cbFrame, &pMixBuf->pi32Samples[0]));
1678 }
1679 }
1680 else
1681 audioMixBufWriteResampling(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cDstMaxFrames, pcDstFramesWritten);
1682}
1683
1684
1685/**
1686 * Worker for AudioMixBufBlend that handles the rate conversion case.
1687 */
1688DECL_NO_INLINE(static, void)
1689audioMixBufBlendResampling(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
1690 uint32_t offDstFrame, uint32_t cDstMaxFrames, uint32_t *pcDstFramesBlended)
1691{
1692 *pcDstFramesBlended = 0;
1693 while (cDstMaxFrames > 0 && cbSrcBuf >= pState->cbSrcFrame)
1694 {
1695 /* Decode into temporary buffer. This then has the destination channel count. */
1696 int32_t ai32Decoded[1024];
1697 uint32_t cFramesDecoded = RT_MIN(RT_ELEMENTS(ai32Decoded) / pState->cDstChannels, cbSrcBuf / pState->cbSrcFrame);
1698 pState->pfnDecode(ai32Decoded, pvSrcBuf, cFramesDecoded, pState);
1699 cbSrcBuf -= cFramesDecoded * pState->cbSrcFrame;
1700 pvSrcBuf = (uint8_t const *)pvSrcBuf + cFramesDecoded * pState->cbSrcFrame;
1701
1702 /* Rate convert that into another temporary buffer and then blend that into the mixer. */
1703 uint32_t iFrameDecoded = 0;
1704 while (iFrameDecoded < cFramesDecoded)
1705 {
1706 int32_t ai32Rate[1024];
1707 uint32_t cDstMaxFramesNow = RT_MIN(RT_ELEMENTS(ai32Rate) / pState->cDstChannels, cDstMaxFrames);
1708 uint32_t cSrcFrames = cFramesDecoded - iFrameDecoded;
1709 uint32_t const cDstFrames = pState->Rate.pfnResample(&ai32Rate[0], cDstMaxFramesNow,
1710 &ai32Decoded[iFrameDecoded * pState->cDstChannels],
1711 cSrcFrames, &cSrcFrames, &pState->Rate);
1712
1713 /* First chunk.*/
1714 uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cDstFrames);
1715 audioMixBufBlendBuffer(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels],
1716 ai32Rate, cDstFrames1, pState->cDstChannels);
1717
1718 /* Another chunk from the start of the mixing buffer? */
1719 if (cDstFrames > cDstFrames1)
1720 audioMixBufBlendBuffer(&pMixBuf->pi32Samples[0], &ai32Rate[cDstFrames1 * pState->cDstChannels],
1721 cDstFrames - cDstFrames1, pState->cDstChannels);
1722
1723 /* Advance */
1724 iFrameDecoded += cSrcFrames;
1725 *pcDstFramesBlended += cDstFrames;
1726 offDstFrame = (offDstFrame + cDstFrames) % pMixBuf->cFrames;
1727 }
1728 }
1729
1730 /** @todo How to squeeze odd frames out of 22050 => 44100 conversion? */
1731}
1732
1733
1734/**
1735 * @todo not sure if 'blend' is the appropriate term here, but you know what
1736 * we mean.
1737 */
1738void AudioMixBufBlend(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
1739 uint32_t offDstFrame, uint32_t cDstMaxFrames, uint32_t *pcDstFramesBlended)
1740{
1741 /*
1742 * Check inputs.
1743 */
1744 AssertPtr(pMixBuf);
1745 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1746 AssertPtr(pState);
1747 AssertPtr(pState->pfnDecode);
1748 AssertPtr(pState->pfnDecodeBlend);
1749 Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
1750 Assert(cDstMaxFrames > 0);
1751 Assert(cDstMaxFrames <= pMixBuf->cFrames - pMixBuf->cUsed);
1752 Assert(offDstFrame <= pMixBuf->cFrames);
1753 AssertPtr(pvSrcBuf);
1754 Assert(!(cbSrcBuf % pState->cbSrcFrame));
1755 AssertPtr(pcDstFramesBlended);
1756
1757 /*
1758 * Make start frame absolute.
1759 */
1760 offDstFrame = (pMixBuf->offWrite + offDstFrame) % pMixBuf->cFrames;
1761
1762 /*
1763 * Hopefully no sample rate conversion is necessary...
1764 */
1765 if (pState->Rate.fNoConversionNeeded)
1766 {
1767 /* Figure out how much we should convert. */
1768 Assert(cDstMaxFrames >= cbSrcBuf / pState->cbSrcFrame);
1769 cDstMaxFrames = RT_MIN(cDstMaxFrames, cbSrcBuf / pState->cbSrcFrame);
1770 *pcDstFramesBlended = cDstMaxFrames;
1771
1772 /* First chunk. */
1773 uint32_t const cDstFrames1 = RT_MIN(pMixBuf->cFrames - offDstFrame, cDstMaxFrames);
1774 pState->pfnDecodeBlend(&pMixBuf->pi32Samples[offDstFrame * pMixBuf->cChannels], pvSrcBuf, cDstFrames1, pState);
1775
1776 /* Another chunk from the start of the mixing buffer? */
1777 if (cDstMaxFrames > cDstFrames1)
1778 pState->pfnDecodeBlend(&pMixBuf->pi32Samples[0], (uint8_t *)pvSrcBuf + cDstFrames1 * pState->cbSrcFrame,
1779 cDstMaxFrames - cDstFrames1, pState);
1780 }
1781 else
1782 audioMixBufBlendResampling(pMixBuf, pState, pvSrcBuf, cbSrcBuf, offDstFrame, cDstMaxFrames, pcDstFramesBlended);
1783}
1784
1785
1786/**
1787 * Writes @a cFrames of silence at @a offFrame relative to current write pos.
1788 *
1789 * This will also adjust the resampling state.
1790 *
1791 * @param pMixBuf The mixing buffer.
1792 * @param pState The write state.
1793 * @param offFrame Where to start writing silence relative to the current
1794 * write position.
1795 * @param cFrames Number of frames of silence.
1796 * @sa AudioMixBufWrite
1797 *
1798 * @note Does not advance the write position, please call AudioMixBufCommit()
1799 * to do that.
1800 */
1801void AudioMixBufSilence(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, uint32_t offFrame, uint32_t cFrames)
1802{
1803 /*
1804 * Check inputs.
1805 */
1806 AssertPtr(pMixBuf);
1807 Assert(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1808 AssertPtr(pState);
1809 AssertPtr(pState->pfnDecode);
1810 AssertPtr(pState->pfnDecodeBlend);
1811 Assert(pState->cDstChannels == PDMAudioPropsChannels(&pMixBuf->Props));
1812 Assert(cFrames > 0);
1813#ifdef VBOX_STRICT
1814 uint32_t const cMixBufFree = pMixBuf->cFrames - pMixBuf->cUsed;
1815#endif
1816 Assert(cFrames <= cMixBufFree);
1817 Assert(offFrame < cMixBufFree);
1818 Assert(offFrame + cFrames <= cMixBufFree);
1819
1820 /*
1821 * Make start frame absolute.
1822 */
1823 offFrame = (pMixBuf->offWrite + offFrame) % pMixBuf->cFrames;
1824
1825 /*
1826 * First chunk.
1827 */
1828 uint32_t const cFramesChunk1 = RT_MIN(pMixBuf->cFrames - offFrame, cFrames);
1829 RT_BZERO(&pMixBuf->pi32Samples[offFrame * pMixBuf->cChannels], cFramesChunk1 * pMixBuf->cbFrame);
1830
1831 /*
1832 * Second chunk, if needed.
1833 */
1834 if (cFrames > cFramesChunk1)
1835 {
1836 cFrames -= cFramesChunk1;
1837 AssertStmt(cFrames <= pMixBuf->cFrames, cFrames = pMixBuf->cFrames);
1838 RT_BZERO(&pMixBuf->pi32Samples[0], cFrames * pMixBuf->cbFrame);
1839 }
1840
1841 /*
1842 * Reset the resampling state.
1843 */
1844 audioMixBufRateReset(&pState->Rate);
1845}
1846
1847
1848/**
1849 * Records a blending gap (silence) of @a cFrames.
1850 *
1851 * This is used to adjust or reset the resampling state so we start from a
1852 * silence state the next time we need to blend or write using @a pState.
1853 *
1854 * @param pMixBuf The mixing buffer.
1855 * @param pState The write state.
1856 * @param cFrames Number of frames of silence.
1857 * @sa AudioMixBufSilence
1858 */
1859void AudioMixBufBlendGap(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, uint32_t cFrames)
1860{
1861 /*
1862 * For now we'll just reset the resampling state regardless of how many
1863 * frames of silence there is.
1864 */
1865 audioMixBufRateReset(&pState->Rate);
1866 RT_NOREF(pMixBuf, cFrames);
1867}
1868
1869
1870/**
1871 * Advances the read position of the buffer.
1872 *
1873 * For use after done peeking with AudioMixBufPeek().
1874 *
1875 * @param pMixBuf The mixing buffer.
1876 * @param cFrames Number of frames to advance.
1877 * @sa AudioMixBufCommit
1878 */
1879void AudioMixBufAdvance(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
1880{
1881 AssertPtrReturnVoid(pMixBuf);
1882 AssertReturnVoid(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
1883
1884 AssertStmt(cFrames <= pMixBuf->cUsed, cFrames = pMixBuf->cUsed);
1885 pMixBuf->cUsed -= cFrames;
1886 pMixBuf->offRead = (pMixBuf->offRead + cFrames) % pMixBuf->cFrames;
1887 LogFlowFunc(("%s: Advanced %u frames: offRead=%u cUsed=%u\n", pMixBuf->pszName, cFrames, pMixBuf->offRead, pMixBuf->cUsed));
1888}
1889
1890
1891/**
1892 * Worker for audioMixAdjustVolume that adjust one contiguous chunk.
1893 */
1894static void audioMixAdjustVolumeWorker(PAUDIOMIXBUF pMixBuf, uint32_t off, uint32_t cFrames)
1895{
1896 int32_t *pi32Samples = &pMixBuf->pi32Samples[off * pMixBuf->cChannels];
1897 switch (pMixBuf->cChannels)
1898 {
1899 case 1:
1900 {
1901 uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
1902 while (cFrames-- > 0)
1903 {
1904 *pi32Samples = (int32_t)(ASMMult2xS32RetS64(*pi32Samples, uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
1905 pi32Samples++;
1906 }
1907 break;
1908 }
1909
1910 case 2:
1911 {
1912 uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
1913 uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
1914 while (cFrames-- > 0)
1915 {
1916 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
1917 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
1918 pi32Samples += 2;
1919 }
1920 break;
1921 }
1922
1923 case 3:
1924 {
1925 uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
1926 uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
1927 uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
1928 while (cFrames-- > 0)
1929 {
1930 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
1931 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
1932 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
1933 pi32Samples += 3;
1934 }
1935 break;
1936 }
1937
1938 case 4:
1939 {
1940 uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
1941 uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
1942 uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
1943 uint32_t const uFactorCh3 = pMixBuf->Volume.auChannels[3];
1944 while (cFrames-- > 0)
1945 {
1946 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
1947 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
1948 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
1949 pi32Samples[3] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[3], uFactorCh3) >> AUDIOMIXBUF_VOL_SHIFT);
1950 pi32Samples += 4;
1951 }
1952 break;
1953 }
1954
1955 case 5:
1956 {
1957 uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
1958 uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
1959 uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
1960 uint32_t const uFactorCh3 = pMixBuf->Volume.auChannels[3];
1961 uint32_t const uFactorCh4 = pMixBuf->Volume.auChannels[4];
1962 while (cFrames-- > 0)
1963 {
1964 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
1965 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
1966 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
1967 pi32Samples[3] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[3], uFactorCh3) >> AUDIOMIXBUF_VOL_SHIFT);
1968 pi32Samples[4] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[4], uFactorCh4) >> AUDIOMIXBUF_VOL_SHIFT);
1969 pi32Samples += 5;
1970 }
1971 break;
1972 }
1973
1974 case 6:
1975 {
1976 uint32_t const uFactorCh0 = pMixBuf->Volume.auChannels[0];
1977 uint32_t const uFactorCh1 = pMixBuf->Volume.auChannels[1];
1978 uint32_t const uFactorCh2 = pMixBuf->Volume.auChannels[2];
1979 uint32_t const uFactorCh3 = pMixBuf->Volume.auChannels[3];
1980 uint32_t const uFactorCh4 = pMixBuf->Volume.auChannels[4];
1981 uint32_t const uFactorCh5 = pMixBuf->Volume.auChannels[5];
1982 while (cFrames-- > 0)
1983 {
1984 pi32Samples[0] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[0], uFactorCh0) >> AUDIOMIXBUF_VOL_SHIFT);
1985 pi32Samples[1] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[1], uFactorCh1) >> AUDIOMIXBUF_VOL_SHIFT);
1986 pi32Samples[2] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[2], uFactorCh2) >> AUDIOMIXBUF_VOL_SHIFT);
1987 pi32Samples[3] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[3], uFactorCh3) >> AUDIOMIXBUF_VOL_SHIFT);
1988 pi32Samples[4] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[4], uFactorCh4) >> AUDIOMIXBUF_VOL_SHIFT);
1989 pi32Samples[5] = (int32_t)(ASMMult2xS32RetS64(pi32Samples[5], uFactorCh5) >> AUDIOMIXBUF_VOL_SHIFT);
1990 pi32Samples += 6;
1991 }
1992 break;
1993 }
1994
1995 default:
1996 while (cFrames-- > 0)
1997 for (uint32_t iCh = 0; iCh < pMixBuf->cChannels; iCh++, pi32Samples++)
1998 *pi32Samples = ASMMult2xS32RetS64(*pi32Samples, pMixBuf->Volume.auChannels[iCh]) >> AUDIOMIXBUF_VOL_SHIFT;
1999 break;
2000 }
2001}
2002
2003
2004/**
2005 * Does volume adjustments for the given stretch of the buffer.
2006 *
2007 * @param pMixBuf The mixing buffer.
2008 * @param offFirst Where to start (validated).
2009 * @param cFrames How many frames (validated).
2010 */
2011static void audioMixAdjustVolume(PAUDIOMIXBUF pMixBuf, uint32_t offFirst, uint32_t cFrames)
2012{
2013 /* Caller has already validated these, so we don't need to repeat that in non-strict builds. */
2014 Assert(offFirst < pMixBuf->cFrames);
2015 Assert(cFrames <= pMixBuf->cFrames);
2016
2017 /*
2018 * Muted?
2019 */
2020 if (pMixBuf->Volume.fMuted)
2021 {
2022 /* first chunk */
2023 uint32_t const cFramesChunk1 = RT_MIN(pMixBuf->cFrames - offFirst, cFrames);
2024 RT_BZERO(&pMixBuf->pi32Samples[offFirst * pMixBuf->cChannels], pMixBuf->cbFrame * cFramesChunk1);
2025
2026 /* second chunk */
2027 if (cFramesChunk1 < cFrames)
2028 RT_BZERO(&pMixBuf->pi32Samples[0], pMixBuf->cbFrame * (cFrames - cFramesChunk1));
2029 }
2030 /*
2031 * Less than max volume?
2032 */
2033 else if (!pMixBuf->Volume.fAllMax)
2034 {
2035 /* first chunk */
2036 uint32_t const cFramesChunk1 = RT_MIN(pMixBuf->cFrames - offFirst, cFrames);
2037 audioMixAdjustVolumeWorker(pMixBuf, offFirst, cFramesChunk1);
2038
2039 /* second chunk */
2040 if (cFramesChunk1 < cFrames)
2041 audioMixAdjustVolumeWorker(pMixBuf, 0, cFrames - cFramesChunk1);
2042 }
2043}
2044
2045
2046/**
2047 * Adjust for volume settings and advances the write position of the buffer.
2048 *
2049 * For use after done peeking with AudioMixBufWrite(), AudioMixBufSilence(),
2050 * AudioMixBufBlend() and AudioMixBufBlendGap().
2051 *
2052 * @param pMixBuf The mixing buffer.
2053 * @param cFrames Number of frames to advance.
2054 * @sa AudioMixBufAdvance, AudioMixBufSetVolume
2055 */
2056void AudioMixBufCommit(PAUDIOMIXBUF pMixBuf, uint32_t cFrames)
2057{
2058 AssertPtrReturnVoid(pMixBuf);
2059 AssertReturnVoid(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC);
2060
2061 AssertStmt(cFrames <= pMixBuf->cFrames - pMixBuf->cUsed, cFrames = pMixBuf->cFrames - pMixBuf->cUsed);
2062
2063 audioMixAdjustVolume(pMixBuf, pMixBuf->offWrite, cFrames);
2064
2065 pMixBuf->cUsed += cFrames;
2066 pMixBuf->offWrite = (pMixBuf->offWrite + cFrames) % pMixBuf->cFrames;
2067 LogFlowFunc(("%s: Advanced %u frames: offWrite=%u cUsed=%u\n", pMixBuf->pszName, cFrames, pMixBuf->offWrite, pMixBuf->cUsed));
2068}
2069
2070
2071/**
2072 * Sets the volume.
2073 *
2074 * The volume adjustments are applied by AudioMixBufCommit().
2075 *
2076 * @param pMixBuf Mixing buffer to set volume for.
2077 * @param pVol Pointer to volume structure to set.
2078 */
2079void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOVOLUME pVol)
2080{
2081 AssertPtrReturnVoid(pMixBuf);
2082 AssertPtrReturnVoid(pVol);
2083
2084 LogFlowFunc(("%s: fMuted=%RTbool auChannels=%.*Rhxs\n",
2085 pMixBuf->pszName, pVol->fMuted, sizeof(pVol->auChannels), pVol->auChannels));
2086
2087 /*
2088 * Convert PDM audio volume to the internal format.
2089 */
2090 if (!pVol->fMuted)
2091 {
2092 pMixBuf->Volume.fMuted = false;
2093
2094 AssertCompileSize(pVol->auChannels[0], sizeof(uint8_t));
2095 for (uintptr_t i = 0; i < pMixBuf->cChannels; i++)
2096 pMixBuf->Volume.auChannels[i] = s_aVolumeConv[pVol->auChannels[i]] * (AUDIOMIXBUF_VOL_0DB >> 16);
2097
2098 pMixBuf->Volume.fAllMax = true;
2099 for (uintptr_t i = 0; i < pMixBuf->cChannels; i++)
2100 if (pMixBuf->Volume.auChannels[i] != AUDIOMIXBUF_VOL_0DB)
2101 {
2102 pMixBuf->Volume.fAllMax = false;
2103 break;
2104 }
2105 }
2106 else
2107 {
2108 pMixBuf->Volume.fMuted = true;
2109 pMixBuf->Volume.fAllMax = false;
2110 for (uintptr_t i = 0; i < RT_ELEMENTS(pMixBuf->Volume.auChannels); i++)
2111 pMixBuf->Volume.auChannels[i] = 0;
2112 }
2113}
2114
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use