summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/Audio/AudioMixBuffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/Audio/AudioMixBuffer.h')
-rw-r--r--src/VBox/Devices/Audio/AudioMixBuffer.h252
1 files changed, 252 insertions, 0 deletions
diff --git a/src/VBox/Devices/Audio/AudioMixBuffer.h b/src/VBox/Devices/Audio/AudioMixBuffer.h
new file mode 100644
index 00000000..a175c5a7
--- /dev/null
+++ b/src/VBox/Devices/Audio/AudioMixBuffer.h
@@ -0,0 +1,252 @@
+/* $Id: AudioMixBuffer.h $ */
+/** @file
+ * Audio Mixing bufer convert audio samples to/from different rates / formats.
+ */
+
+/*
+ * 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
+ */
+
+#ifndef VBOX_INCLUDED_SRC_Audio_AudioMixBuffer_h
+#define VBOX_INCLUDED_SRC_Audio_AudioMixBuffer_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <VBox/vmm/pdmaudioifs.h>
+
+/** @defgroup grp_pdm_ifs_audio_mixing_buffers Audio Mixing Buffers
+ * @ingroup grp_pdm_ifs_audio_mixing
+ *
+ * @note This is currently placed under PDM Audio Interface as that seemed like
+ * the best place for it.
+ *
+ * @{
+ */
+
+
+/**
+ * Rate processing information of a source & destination audio stream.
+ *
+ * This is needed because both streams can differ regarding their rates and
+ * therefore need to be treated accordingly.
+ */
+typedef struct AUDIOSTREAMRATE
+{
+ /** Current (absolute) offset in the output (destination) stream.
+ * @todo r=bird: Please reveal which unit these members are given in. */
+ uint64_t offDst;
+ /** Increment for moving offDst for the destination stream.
+ * This is needed because the source <-> destination rate might be different. */
+ uint64_t uDstInc;
+ /** Current (absolute) offset in the input stream. */
+ uint32_t offSrc;
+ /** Set if no conversion is necessary. */
+ bool fNoConversionNeeded;
+ bool afPadding[3];
+
+ /** Last processed frame of the input stream.
+ * Needed for interpolation. */
+ union
+ {
+ int32_t ai32Samples[PDMAUDIO_MAX_CHANNELS];
+ } SrcLast;
+
+ /**
+ * Resampling function.
+ * @returns Number of destination frames written.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnResample, (int32_t *pi32Dst, uint32_t cDstFrames,
+ int32_t const *pi32Src, uint32_t cSrcFrames, uint32_t *pcSrcFramesRead,
+ struct AUDIOSTREAMRATE *pRate));
+
+} AUDIOSTREAMRATE;
+/** Pointer to rate processing information of a stream. */
+typedef AUDIOSTREAMRATE *PAUDIOSTREAMRATE;
+
+/**
+ * Mixing buffer volume parameters.
+ *
+ * The volume values are in fixed point style and must be converted to/from
+ * before using with e.g. PDMAUDIOVOLUME.
+ */
+typedef struct AUDMIXBUFVOL
+{
+ /** Set to @c true if this stream is muted, @c false if not. */
+ bool fMuted;
+ /** Set if all (relevant) channels are at max. */
+ bool fAllMax;
+ /** The per-channels values. */
+ uint32_t auChannels[PDMAUDIO_MAX_CHANNELS];
+} AUDMIXBUFVOL;
+/** Pointer to mixing buffer volument parameters. */
+typedef AUDMIXBUFVOL *PAUDMIXBUFVOL;
+
+
+/** Pointer to audio mixing buffer. */
+typedef struct AUDIOMIXBUF *PAUDIOMIXBUF;
+/** Pointer to a const audio mixing buffer. */
+typedef struct AUDIOMIXBUF const *PCAUDIOMIXBUF;
+
+
+/**
+ * State & config for AudioMixBufPeek created by AudioMixBufInitPeekState.
+ */
+typedef struct AUDIOMIXBUFPEEKSTATE
+{
+ /** Encodes @a cFrames from @a paSrc to @a pvDst. */
+ DECLR3CALLBACKMEMBER(void, pfnEncode,(void *pvDst, int32_t const *paSrc, uint32_t cFrames, struct AUDIOMIXBUFPEEKSTATE *pState));
+ /** Sample rate conversion state (only used when needed). */
+ AUDIOSTREAMRATE Rate;
+ /** Source (mixer) channels. */
+ uint8_t cSrcChannels;
+ /** Destination channels. */
+ uint8_t cDstChannels;
+ /** Destination frame size. */
+ uint8_t cbDstFrame;
+ /** The destination frame layout described as indexes into the source frame.
+ * This ASSUMES that all channels uses the same sample size, so one sample per
+ * channel if you like.
+ * Negative values are special: -1 for zero, -2 for silence.
+ * @note Blending stereo into mono is not really expressible here. */
+ int8_t aidxChannelMap[PDMAUDIO_MAX_CHANNELS];
+} AUDIOMIXBUFPEEKSTATE;
+/** Pointer to peek state & config. */
+typedef AUDIOMIXBUFPEEKSTATE *PAUDIOMIXBUFPEEKSTATE;
+
+
+/**
+ * State & config for AudioMixBufWrite, AudioMixBufSilence, AudioMixBufBlend and
+ * AudioMixBufBlendGap, created by AudioMixBufInitWriteState.
+ */
+typedef struct AUDIOMIXBUFWRITESTATE
+{
+ /** Encodes @a cFrames from @a pvSrc to @a paDst. */
+ DECLR3CALLBACKMEMBER(void, pfnDecode,(int32_t *paDst, const void *pvSrc, uint32_t cFrames, struct AUDIOMIXBUFWRITESTATE *pState));
+ /** Encodes @a cFrames from @a pvSrc blending into @a paDst. */
+ DECLR3CALLBACKMEMBER(void, pfnDecodeBlend,(int32_t *paDst, const void *pvSrc, uint32_t cFrames, struct AUDIOMIXBUFWRITESTATE *pState));
+ /** Sample rate conversion state (only used when needed). */
+ AUDIOSTREAMRATE Rate;
+ /** Destination (mixer) channels. */
+ uint8_t cDstChannels;
+ /** Source hannels. */
+ uint8_t cSrcChannels;
+ /** Source frame size. */
+ uint8_t cbSrcFrame;
+ /** The destination frame layout described as indexes into the source frame.
+ * This ASSUMES that all channels uses the same sample size, so one sample per
+ * channel if you like.
+ * Negative values are special: -1 for zero, -2 for silence.
+ * @note Blending stereo into mono is not really expressible here. */
+ int8_t aidxChannelMap[PDMAUDIO_MAX_CHANNELS];
+} AUDIOMIXBUFWRITESTATE;
+/** Pointer to write state & config. */
+typedef AUDIOMIXBUFWRITESTATE *PAUDIOMIXBUFWRITESTATE;
+
+
+/**
+ * Audio mixing buffer.
+ */
+typedef struct AUDIOMIXBUF
+{
+ /** Magic value (AUDIOMIXBUF_MAGIC). */
+ uint32_t uMagic;
+ /** Size of the frame buffer (in audio frames). */
+ uint32_t cFrames;
+ /** The frame buffer.
+ * This is a two dimensional array consisting of cFrames rows and
+ * cChannels columns. */
+ int32_t *pi32Samples;
+ /** The number of channels. */
+ uint8_t cChannels;
+ /** The frame size (row size if you like). */
+ uint8_t cbFrame;
+ uint8_t abPadding[2];
+ /** The current read position (in frames). */
+ uint32_t offRead;
+ /** The current write position (in frames). */
+ uint32_t offWrite;
+ /** How much audio frames are currently being used in this buffer.
+ * @note This also is known as the distance in ring buffer terms. */
+ uint32_t cUsed;
+ /** Audio properties for the buffer content - for frequency and channel count.
+ * (This is the guest side PCM properties.) */
+ PDMAUDIOPCMPROPS Props;
+ /** Internal representation of current volume used for mixing. */
+ AUDMIXBUFVOL Volume;
+ /** Name of the buffer. */
+ char *pszName;
+} AUDIOMIXBUF;
+
+/** Magic value for AUDIOMIXBUF (Antonio Lucio Vivaldi). */
+#define AUDIOMIXBUF_MAGIC UINT32_C(0x16780304)
+/** Dead mixer buffer magic. */
+#define AUDIOMIXBUF_MAGIC_DEAD UINT32_C(0x17410728)
+
+/** Converts (audio) frames to bytes. */
+#define AUDIOMIXBUF_F2B(a_pMixBuf, a_cFrames) PDMAUDIOPCMPROPS_F2B(&(a_pMixBuf)->Props, a_cFrames)
+/** Converts bytes to (audio) frames.
+ * @note Does *not* take the conversion ratio into account. */
+#define AUDIOMIXBUF_B2F(a_pMixBuf, a_cb) PDMAUDIOPCMPROPS_B2F(&(a_pMixBuf)->Props, a_cb)
+
+
+int AudioMixBufInit(PAUDIOMIXBUF pMixBuf, const char *pszName, PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);
+void AudioMixBufTerm(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufDrop(PAUDIOMIXBUF pMixBuf);
+void AudioMixBufSetVolume(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOVOLUME pVol);
+
+/** @name Mixer buffer getters
+ * @{ */
+uint32_t AudioMixBufSize(PCAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufSizeBytes(PCAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufUsed(PCAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufUsedBytes(PCAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufFree(PCAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufFreeBytes(PCAUDIOMIXBUF pMixBuf);
+bool AudioMixBufIsEmpty(PCAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufReadPos(PCAUDIOMIXBUF pMixBuf);
+uint32_t AudioMixBufWritePos(PCAUDIOMIXBUF pMixBuf);
+/** @} */
+
+/** @name Mixer buffer reading
+ * @{ */
+int AudioMixBufInitPeekState(PCAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFPEEKSTATE pState, PCPDMAUDIOPCMPROPS pDstProps);
+void AudioMixBufPeek(PCAUDIOMIXBUF pMixBuf, uint32_t offSrcFrame, uint32_t cMaxSrcFrames, uint32_t *pcSrcFramesPeeked,
+ PAUDIOMIXBUFPEEKSTATE pState, void *pvDst, uint32_t cbDst, uint32_t *pcbDstPeeked);
+void AudioMixBufAdvance(PAUDIOMIXBUF pMixBuf, uint32_t cFrames);
+/** @} */
+
+/** @name Mixer buffer writing
+ * @{ */
+int AudioMixBufInitWriteState(PCAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, PCPDMAUDIOPCMPROPS pSrcProps);
+void AudioMixBufWrite(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
+ uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesWritten);
+void AudioMixBufSilence(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, uint32_t offFrame, uint32_t cFrames);
+void AudioMixBufBlend(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, const void *pvSrcBuf, uint32_t cbSrcBuf,
+ uint32_t offDstFrame, uint32_t cMaxDstFrames, uint32_t *pcDstFramesBlended);
+void AudioMixBufBlendGap(PAUDIOMIXBUF pMixBuf, PAUDIOMIXBUFWRITESTATE pState, uint32_t cFrames);
+void AudioMixBufCommit(PAUDIOMIXBUF pMixBuf, uint32_t cFrames);
+/** @} */
+
+/** @} */
+#endif /* !VBOX_INCLUDED_SRC_Audio_AudioMixBuffer_h */
+