summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/Audio/AudioMixBuffer.h
blob: a175c5a77018dd26a224375fe35fb664119e0e8d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
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 */