VirtualBox

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

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