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
253
254
255
256
257
258
259
260
261
262
263
|
/* $Id: AudioMixer.h $ */
/** @file
* VBox audio - Mixing routines.
*
* The mixing routines are mainly used by the various audio device emulations
* to achieve proper multiplexing from/to attached devices LUNs.
*/
/*
* Copyright (C) 2014-2019 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#ifndef VBOX_INCLUDED_SRC_Audio_AudioMixer_h
#define VBOX_INCLUDED_SRC_Audio_AudioMixer_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
#include <iprt/cdefs.h>
#include <iprt/critsect.h>
#include <VBox/vmm/pdmaudioifs.h>
/**
* Structure for maintaining an audio mixer instance.
*/
typedef struct AUDIOMIXER
{
/** The mixer's name. */
char *pszName;
/** The mixer's critical section. */
RTCRITSECT CritSect;
/** The master volume of this mixer. */
PDMAUDIOVOLUME VolMaster;
/** List of audio mixer sinks. */
RTLISTANCHOR lstSinks;
/** Number of used audio sinks. */
uint8_t cSinks;
} AUDIOMIXER, *PAUDIOMIXER;
/** Defines an audio mixer stream's flags. */
#define AUDMIXSTREAMFLAGS uint32_t
/** No flags specified. */
#define AUDMIXSTREAM_FLAG_NONE 0
/** Prototype needed for AUDMIXSTREAM struct definition. */
typedef struct AUDMIXSINK *PAUDMIXSINK;
/**
* Structure for maintaining an audio mixer stream.
*/
typedef struct AUDMIXSTREAM
{
/** List node. */
RTLISTNODE Node;
/** Name of this stream. */
char *pszName;
/** The streams's critical section. */
RTCRITSECT CritSect;
/** Sink this stream is attached to. */
PAUDMIXSINK pSink;
/** Stream flags of type AUDMIXSTREAM_FLAG_. */
uint32_t fFlags;
/** Pointer to audio connector being used. */
PPDMIAUDIOCONNECTOR pConn;
/** Pointer to PDM audio stream this mixer stream handles. */
PPDMAUDIOSTREAM pStream;
/** Last read (recording) / written (playback) timestamp (in ns). */
uint64_t tsLastReadWrittenNs;
/** The stream's circular buffer for temporarily
* holding (raw) device audio data. */
PRTCIRCBUF pCircBuf;
} AUDMIXSTREAM, *PAUDMIXSTREAM;
/** Defines an audio sink's current status. */
#define AUDMIXSINKSTS uint32_t
/** No status specified. */
#define AUDMIXSINK_STS_NONE 0
/** The sink is active and running. */
#define AUDMIXSINK_STS_RUNNING RT_BIT(0)
/** The sink is in a pending disable state. */
#define AUDMIXSINK_STS_PENDING_DISABLE RT_BIT(1)
/** Dirty flag.
* For output sinks this means that there is data in the
* sink which has not been played yet.
* For input sinks this means that there is data in the
* sink which has been recorded but not transferred to the
* destination yet. */
#define AUDMIXSINK_STS_DIRTY RT_BIT(2)
/**
* Audio mixer sink direction.
*/
typedef enum AUDMIXSINKDIR
{
/** Unknown direction. */
AUDMIXSINKDIR_UNKNOWN = 0,
/** Input (capturing from a device). */
AUDMIXSINKDIR_INPUT,
/** Output (playing to a device). */
AUDMIXSINKDIR_OUTPUT,
/** The usual 32-bit hack. */
AUDMIXSINKDIR_32BIT_HACK = 0x7fffffff
} AUDMIXSINKDIR;
/**
* Audio mixer sink command.
*/
typedef enum AUDMIXSINKCMD
{
/** Unknown command, do not use. */
AUDMIXSINKCMD_UNKNOWN = 0,
/** Enables the sink. */
AUDMIXSINKCMD_ENABLE,
/** Disables the sink. */
AUDMIXSINKCMD_DISABLE,
/** Pauses the sink. */
AUDMIXSINKCMD_PAUSE,
/** Resumes the sink. */
AUDMIXSINKCMD_RESUME,
/** Tells the sink's streams to drop all (buffered) data immediately. */
AUDMIXSINKCMD_DROP,
/** Hack to blow the type up to 32-bit. */
AUDMIXSINKCMD_32BIT_HACK = 0x7fffffff
} AUDMIXSINKCMD;
/**
* Structure for keeping audio input sink specifics.
* Do not use directly. Instead, use AUDMIXSINK.
*/
typedef struct AUDMIXSINKIN
{
/** The current recording source. Can be NULL if not set. */
PAUDMIXSTREAM pStreamRecSource;
} AUDMIXSINKIN;
/**
* Structure for keeping audio output sink specifics.
* Do not use directly. Instead, use AUDMIXSINK.
*/
typedef struct AUDMIXSINKOUT
{
} AUDMIXSINKOUT;
/**
* Structure for maintaining an audio mixer sink.
*/
typedef struct AUDMIXSINK
{
RTLISTNODE Node;
/** Pointer to mixer object this sink is bound to. */
PAUDIOMIXER pParent;
/** Name of this sink. */
char *pszName;
/** The sink direction, that is,
* if this sink handles input or output. */
AUDMIXSINKDIR enmDir;
/** The sink's critical section. */
RTCRITSECT CritSect;
/** This sink's mixing buffer, acting as
* a parent buffer for all streams this sink owns. */
PDMAUDIOMIXBUF MixBuf;
/** Union for input/output specifics. */
union
{
AUDMIXSINKIN In;
AUDMIXSINKOUT Out;
};
/** Sink status of type AUDMIXSINK_STS_XXX. */
AUDMIXSINKSTS fStatus;
/** The sink's PCM format. */
PDMAUDIOPCMPROPS PCMProps;
/** Number of streams assigned. */
uint8_t cStreams;
/** List of assigned streams.
* Note: All streams have the same PCM properties, so the
* mixer does not do any conversion. */
/** @todo Use something faster -- vector maybe? */
RTLISTANCHOR lstStreams;
/** The volume of this sink. The volume always will
* be combined with the mixer's master volume. */
PDMAUDIOVOLUME Volume;
/** The volume of this sink, combined with the last set master volume. */
PDMAUDIOVOLUME VolumeCombined;
/** Timestamp since last update (in ms). */
uint64_t tsLastUpdatedMs;
/** Last read (recording) / written (playback) timestamp (in ns). */
uint64_t tsLastReadWrittenNs;
#ifdef VBOX_AUDIO_MIXER_DEBUG
struct
{
PPDMAUDIOFILE pFile;
} Dbg;
#endif
} AUDMIXSINK, *PAUDMIXSINK;
/**
* Audio mixer operation.
*/
typedef enum AUDMIXOP
{
/** Invalid operation, do not use. */
AUDMIXOP_INVALID = 0,
/** Copy data from A to B, overwriting data in B. */
AUDMIXOP_COPY,
/** Blend data from A with (existing) data in B. */
AUDMIXOP_BLEND,
/** The usual 32-bit hack. */
AUDMIXOP_32BIT_HACK = 0x7fffffff
} AUDMIXOP;
/** No flags specified. */
#define AUDMIXSTRMCTL_FLAG_NONE 0
int AudioMixerCreate(const char *pszName, uint32_t uFlags, PAUDIOMIXER *ppMixer);
int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PAUDMIXSINK *ppSink);
void AudioMixerDestroy(PAUDIOMIXER pMixer);
void AudioMixerInvalidate(PAUDIOMIXER pMixer);
void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink);
int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol);
void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs);
int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
int AudioMixerSinkCreateStream(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOSTREAMCFG pCfg, AUDMIXSTREAMFLAGS fFlags, PAUDMIXSTREAM *ppStream);
int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd);
void AudioMixerSinkDestroy(PAUDMIXSINK pSink);
uint32_t AudioMixerSinkGetReadable(PAUDMIXSINK pSink);
uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink);
AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink);
const char *AudioMixerSinkGetName(const PAUDMIXSINK pSink);
PAUDMIXSTREAM AudioMixerSinkGetRecordingSource(PAUDMIXSINK pSink);
PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex);
AUDMIXSINKSTS AudioMixerSinkGetStatus(PAUDMIXSINK pSink);
uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink);
bool AudioMixerSinkIsActive(PAUDMIXSINK pSink);
int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
void AudioMixerSinkRemoveAllStreams(PAUDMIXSINK pSink);
void AudioMixerSinkReset(PAUDMIXSINK pSink);
void AudioMixerSinkGetFormat(PAUDMIXSINK pSink, PPDMAUDIOPCMPROPS pPCMProps);
int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PPDMAUDIOPCMPROPS pPCMProps);
int AudioMixerSinkSetRecordingSource(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);
int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
int AudioMixerSinkUpdate(PAUDMIXSINK pSink);
int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl);
void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream);
bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream);
bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream);
#endif /* !VBOX_INCLUDED_SRC_Audio_AudioMixer_h */
|