VirtualBox

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

Last change on this file since 103914 was 98103, checked in by vboxsync, 21 months ago

Copyright year updates by scm.

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette