diff options
Diffstat (limited to 'src/VBox/Devices/Audio/AudioMixBuffer-Convert.cpp.h')
-rw-r--r-- | src/VBox/Devices/Audio/AudioMixBuffer-Convert.cpp.h | 315 |
1 files changed, 315 insertions, 0 deletions
diff --git a/src/VBox/Devices/Audio/AudioMixBuffer-Convert.cpp.h b/src/VBox/Devices/Audio/AudioMixBuffer-Convert.cpp.h new file mode 100644 index 00000000..3913449b --- /dev/null +++ b/src/VBox/Devices/Audio/AudioMixBuffer-Convert.cpp.h @@ -0,0 +1,315 @@ +/* $Id: AudioMixBuffer-Convert.cpp.h $ */ +/** @file + * Audio mixing buffer - Format conversion template. + */ + +/* + * Copyright (C) 2014-2023 Oracle and/or its affiliates. + * + * This file is part of VirtualBox base platform packages, as + * available from https://www.virtualbox.org. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, in version 3 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <https://www.gnu.org/licenses>. + * + * SPDX-License-Identifier: GPL-3.0-only + */ + + +/* used to be: #define AUDMIXBUF_CONVERT(a_Name, a_Type, a_Min, a_Max, a_fSigned, a_cShift) */ + +/* Clips a specific output value to a single sample value. */ +DECLINLINE(int32_t) RT_CONCAT(audioMixBufSampleFrom,a_Name)(a_Type aVal) +{ + /* left shifting of signed values is not defined, therefore the intermediate uint64_t cast */ + if (a_fSigned) + return (int32_t) (((uint32_t) ((int32_t) aVal )) << (32 - a_cShift)); + return (int32_t) (((uint32_t) ((int32_t) aVal - ((a_Max >> 1) + 1))) << (32 - a_cShift)); +} + +/* Clips a single sample value to a specific output value. */ +DECLINLINE(a_Type) RT_CONCAT(audioMixBufSampleTo,a_Name)(int32_t iVal) +{ + if (a_fSigned) + return (a_Type) (iVal >> (32 - a_cShift)); + return (a_Type) ((iVal >> (32 - a_cShift)) + ((a_Max >> 1) + 1)); +} + +/* Encoders for peek: */ + +/* Generic */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufEncodeGeneric,a_Name)(void *pvDst, int32_t const *pi32Src, uint32_t cFrames, + PAUDIOMIXBUFPEEKSTATE pState) +{ + RT_NOREF_PV(pState); + uintptr_t const cSrcChannels = pState->cSrcChannels; + uintptr_t const cDstChannels = pState->cDstChannels; + a_Type *pDst = (a_Type *)pvDst; + while (cFrames-- > 0) + { + uintptr_t idxDst = cDstChannels; + while (idxDst-- > 0) + { + intptr_t idxSrc = pState->aidxChannelMap[idxDst]; + if (idxSrc >= 0) + pDst[idxDst] = RT_CONCAT(audioMixBufSampleTo,a_Name)(pi32Src[idxSrc]); + else if (idxSrc != -2) + pDst[idxDst] = (a_fSigned) ? 0 : (a_Max >> 1); + else + pDst[idxDst] = 0; + } + pDst += cDstChannels; + pi32Src += cSrcChannels; + } +} + +/* 2ch -> 2ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufEncode2ChTo2Ch,a_Name)(void *pvDst, int32_t const *pi32Src, uint32_t cFrames, + PAUDIOMIXBUFPEEKSTATE pState) +{ + RT_NOREF_PV(pState); + a_Type *pDst = (a_Type *)pvDst; + while (cFrames-- > 0) + { + pDst[0] = RT_CONCAT(audioMixBufSampleTo,a_Name)(pi32Src[0]); + pDst[1] = RT_CONCAT(audioMixBufSampleTo,a_Name)(pi32Src[1]); + AUDMIXBUF_MACRO_LOG(("%p: %RI32 / %RI32 => %RI32 / %RI32\n", + &pi32Src[0], pi32Src[0], pi32Src[1], (int32_t)pDst[0], (int32_t)pDst[1])); + pDst += 2; + pi32Src += 2; + } +} + +/* 2ch -> 1ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufEncode2ChTo1Ch,a_Name)(void *pvDst, int32_t const *pi32Src, uint32_t cFrames, + PAUDIOMIXBUFPEEKSTATE pState) +{ + RT_NOREF_PV(pState); + a_Type *pDst = (a_Type *)pvDst; + while (cFrames-- > 0) + { + pDst[0] = RT_CONCAT(audioMixBufSampleTo,a_Name)(audioMixBufBlendSampleRet(pi32Src[0], pi32Src[1])); + pDst += 1; + pi32Src += 2; + } +} + +/* 1ch -> 2ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufEncode1ChTo2Ch,a_Name)(void *pvDst, int32_t const *pi32Src, uint32_t cFrames, + PAUDIOMIXBUFPEEKSTATE pState) +{ + RT_NOREF_PV(pState); + a_Type *pDst = (a_Type *)pvDst; + while (cFrames-- > 0) + { + pDst[0] = pDst[1] = RT_CONCAT(audioMixBufSampleTo,a_Name)(pi32Src[0]); + pDst += 2; + pi32Src += 1; + } +} +/* 1ch -> 1ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufEncode1ChTo1Ch,a_Name)(void *pvDst, int32_t const *pi32Src, uint32_t cFrames, + PAUDIOMIXBUFPEEKSTATE pState) +{ + RT_NOREF_PV(pState); + a_Type *pDst = (a_Type *)pvDst; + while (cFrames-- > 0) + { + pDst[0] = RT_CONCAT(audioMixBufSampleTo,a_Name)(pi32Src[0]); + pDst += 1; + pi32Src += 1; + } +} + +/* Decoders for write: */ + +/* Generic */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufDecodeGeneric,a_Name)(int32_t *pi32Dst, void const *pvSrc, uint32_t cFrames, + PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + uintptr_t const cSrcChannels = pState->cSrcChannels; + uintptr_t const cDstChannels = pState->cDstChannels; + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + uintptr_t idxDst = cDstChannels; + while (idxDst-- > 0) + { + intptr_t idxSrc = pState->aidxChannelMap[idxDst]; + if (idxSrc >= 0) + pi32Dst[idxDst] = RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[idxSrc]); + else if (idxSrc != -2) + pi32Dst[idxDst] = (a_fSigned) ? 0 : (a_Max >> 1); + else + pi32Dst[idxDst] = 0; + } + pi32Dst += cDstChannels; + pSrc += cSrcChannels; + } +} + +/* 2ch -> 2ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufDecode2ChTo2Ch,a_Name)(int32_t *pi32Dst, void const *pvSrc, uint32_t cFrames, + PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + pi32Dst[0] = RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0]); + pi32Dst[1] = RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[1]); + AUDMIXBUF_MACRO_LOG(("%p: %RI32 / %RI32 => %RI32 / %RI32\n", + &pSrc[0], (int32_t)pSrc[0], (int32_t)pSrc[1], pi32Dst[0], pi32Dst[1])); + pi32Dst += 2; + pSrc += 2; + } +} + +/* 2ch -> 1ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufDecode2ChTo1Ch,a_Name)(int32_t *pi32Dst, void const *pvSrc, uint32_t cFrames, + PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + pi32Dst[0] = audioMixBufBlendSampleRet(RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0]), + RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[1])); + pi32Dst += 1; + pSrc += 2; + } +} + +/* 1ch -> 2ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufDecode1ChTo2Ch,a_Name)(int32_t *pi32Dst, void const *pvSrc, uint32_t cFrames, + PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + pi32Dst[1] = pi32Dst[0] = RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0]); + pi32Dst += 2; + pSrc += 1; + } +} + +/* 1ch -> 1ch */ +static DECLCALLBACK(void) RT_CONCAT(audioMixBufDecode1ChTo1Ch,a_Name)(int32_t *pi32Dst, void const *pvSrc, uint32_t cFrames, + PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + pi32Dst[0] = RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0]); + pi32Dst += 1; + pSrc += 1; + } +} + +/* Decoders for blending: */ + +/* Generic */ +static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecodeGeneric,a_Name,Blend)(int32_t *pi32Dst, void const *pvSrc, + uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + uintptr_t const cSrcChannels = pState->cSrcChannels; + uintptr_t const cDstChannels = pState->cDstChannels; + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + uintptr_t idxDst = cDstChannels; + while (idxDst-- > 0) + { + intptr_t idxSrc = pState->aidxChannelMap[idxDst]; + if (idxSrc >= 0) + audioMixBufBlendSample(&pi32Dst[idxDst], RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[idxSrc])); + } + pi32Dst += cDstChannels; + pSrc += cSrcChannels; + } +} + +/* 2ch -> 2ch */ +static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode2ChTo2Ch,a_Name,Blend)(int32_t *pi32Dst, void const *pvSrc, + uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + audioMixBufBlendSample(&pi32Dst[0], RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0])); + audioMixBufBlendSample(&pi32Dst[1], RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[1])); + AUDMIXBUF_MACRO_LOG(("%p: %RI32 / %RI32 => %RI32 / %RI32\n", + &pSrc[0], (int32_t)pSrc[0], (int32_t)pSrc[1], pi32Dst[0], pi32Dst[1])); + pi32Dst += 2; + pSrc += 2; + } +} + +/* 2ch -> 1ch */ +static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode2ChTo1Ch,a_Name,Blend)(int32_t *pi32Dst, void const *pvSrc, + uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + audioMixBufBlendSample(&pi32Dst[0], audioMixBufBlendSampleRet(RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0]), + RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[1]))); + pi32Dst += 1; + pSrc += 2; + } +} + +/* 1ch -> 2ch */ +static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode1ChTo2Ch,a_Name,Blend)(int32_t *pi32Dst, void const *pvSrc, + uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + int32_t const i32Src = RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0]); + audioMixBufBlendSample(&pi32Dst[0], i32Src); + audioMixBufBlendSample(&pi32Dst[1], i32Src); + pi32Dst += 2; + pSrc += 1; + } +} + +/* 1ch -> 1ch */ +static DECLCALLBACK(void) RT_CONCAT3(audioMixBufDecode1ChTo1Ch,a_Name,Blend)(int32_t *pi32Dst, void const *pvSrc, + uint32_t cFrames, PAUDIOMIXBUFWRITESTATE pState) +{ + RT_NOREF_PV(pState); + a_Type const *pSrc = (a_Type const *)pvSrc; + while (cFrames-- > 0) + { + audioMixBufBlendSample(&pi32Dst[0], RT_CONCAT(audioMixBufSampleFrom,a_Name)(pSrc[0])); + pi32Dst += 1; + pSrc += 1; + } +} + + +#undef a_Name +#undef a_Type +#undef a_Min +#undef a_Max +#undef a_fSigned +#undef a_cShift + |