summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/Audio/AudioMixer.h
blob: 7f62d3c79f2519d3bdd196461991975331b8b98c (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
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 */