VirtualBox

source: vbox/trunk/src/VBox/Devices/Audio/AudioMixer.h@ 88443

Last change on this file since 88443 was 88433, checked in by vboxsync, 4 years ago

Audio: Eliminated the DrvAudio mixing buffers for output streams on devices without their own mixer. Changed the prebuffering to not default to the whole backend buffer size, but only 2/3 of it, so that there is room for a bit of incoming data from the device once we start playing. We don't want to have that gather in the device mixer or internal DMA buffers. This code needs some more testing and work, only tested on linux against ALSA. bugref:9890

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* $Id: AudioMixer.h 88433 2021-04-09 12:55:19Z vboxsync $ */
2/** @file
3 * VBox audio - Mixing routines.
4 *
5 * The mixing routines are mainly used by the various audio device emulations
6 * to achieve proper multiplexing from/to attached devices LUNs.
7 */
8
9/*
10 * Copyright (C) 2014-2020 Oracle Corporation
11 *
12 * This file is part of VirtualBox Open Source Edition (OSE), as
13 * available from http://www.virtualbox.org. This file is free software;
14 * you can redistribute it and/or modify it under the terms of the GNU
15 * General Public License (GPL) as published by the Free Software
16 * Foundation, in version 2 as it comes in the "COPYING" file of the
17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
19 */
20
21#ifndef VBOX_INCLUDED_SRC_Audio_AudioMixer_h
22#define VBOX_INCLUDED_SRC_Audio_AudioMixer_h
23#ifndef RT_WITHOUT_PRAGMA_ONCE
24# pragma once
25#endif
26
27#include <iprt/cdefs.h>
28#include <iprt/critsect.h>
29
30#include <VBox/vmm/pdmaudioifs.h>
31#include "AudioMixBuffer.h"
32#include "AudioHlp.h"
33
34
35/** Pointer to an audio mixer sink. */
36typedef struct AUDMIXSINK *PAUDMIXSINK;
37
38
39/**
40 * Audio mixer instance.
41 */
42typedef struct AUDIOMIXER
43{
44 /** The mixer's name. */
45 char *pszName;
46 /** The mixer's critical section. */
47 RTCRITSECT CritSect;
48 /** The master volume of this mixer. */
49 PDMAUDIOVOLUME VolMaster;
50 /** List of audio mixer sinks. */
51 RTLISTANCHOR lstSinks;
52 /** Number of used audio sinks. */
53 uint8_t cSinks;
54 /** Mixer flags. See AUDMIXER_FLAGS_XXX. */
55 uint32_t fFlags;
56} AUDIOMIXER;
57/** Pointer to an audio mixer instance. */
58typedef AUDIOMIXER *PAUDIOMIXER;
59
60
61/** Defines an audio mixer stream's flags. */
62#define AUDMIXSTREAMFLAGS uint32_t
63
64/** No flags specified. */
65#define AUDMIXSTREAM_F_NONE 0
66/** The mixing stream is flagged as being enabled (active). */
67#define AUDMIXSTREAM_F_ENABLED RT_BIT(0)
68
69/** Defines an audio mixer stream's internal status. */
70#define AUDMIXSTREAMSTATUS uint32_t
71
72/** No status set. */
73#define AUDMIXSTREAM_STATUS_NONE 0
74/** The mixing stream is enabled (active). */
75#define AUDMIXSTREAM_STATUS_ENABLED RT_BIT(0)
76/** The mixing stream can be read from. */
77#define AUDMIXSTREAM_STATUS_CAN_READ RT_BIT(1)
78/** The mixing stream can be written to. */
79#define AUDMIXSTREAM_STATUS_CAN_WRITE RT_BIT(2)
80
81
82/**
83 * Audio mixer stream.
84 */
85typedef struct AUDMIXSTREAM
86{
87 /** List node. */
88 RTLISTNODE Node;
89 /** Name of this stream. */
90 char *pszName;
91 /** The statistics prefix. */
92 char *pszStatPrefix;
93 /** Sink this stream is attached to. */
94 PAUDMIXSINK pSink;
95 /** Stream flags of type AUDMIXSTREAM_F_. */
96 uint32_t fFlags;
97 /** Stream status of type AUDMIXSTREAM_STATUS_. */
98 uint32_t fStatus;
99 /** Pointer to audio connector being used. */
100 PPDMIAUDIOCONNECTOR pConn;
101 /** Pointer to PDM audio stream this mixer stream handles. */
102 PPDMAUDIOSTREAM pStream;
103 /** Mixing buffer peeking state & config. */
104 AUDIOMIXBUFPEEKSTATE PeekState;
105 /** Last read (recording) / written (playback) timestamp (in ns). */
106 uint64_t tsLastReadWrittenNs;
107 /** The streams's critical section. */
108 RTCRITSECT CritSect;
109} AUDMIXSTREAM, *PAUDMIXSTREAM;
110
111/** Defines an audio sink's current status. */
112#define AUDMIXSINKSTS uint32_t
113
114/** No status specified. */
115#define AUDMIXSINK_STS_NONE 0
116/** The sink is active and running. */
117#define AUDMIXSINK_STS_RUNNING RT_BIT(0)
118/** The sink is in a pending disable state. */
119#define AUDMIXSINK_STS_PENDING_DISABLE RT_BIT(1)
120/** Dirty flag.
121 * - For output sinks this means that there is data in the sink which has not
122 * been played yet.
123 * - For input sinks this means that there is data in the sink which has been
124 * recorded but not transferred to the destination yet. */
125#define AUDMIXSINK_STS_DIRTY RT_BIT(2)
126
127/**
128 * Audio mixer sink direction.
129 * @todo r=bird: use PDMAUDIODIR instead.
130 */
131typedef enum AUDMIXSINKDIR
132{
133 /** Unknown direction. */
134 AUDMIXSINKDIR_UNKNOWN = 0,
135 /** Input (capturing from a device). */
136 AUDMIXSINKDIR_INPUT,
137 /** Output (playing to a device). */
138 AUDMIXSINKDIR_OUTPUT,
139 /** The usual 32-bit hack. */
140 AUDMIXSINKDIR_32BIT_HACK = 0x7fffffff
141} AUDMIXSINKDIR;
142
143/**
144 * Audio mixer sink command.
145 */
146typedef enum AUDMIXSINKCMD
147{
148 /** Unknown command, do not use. */
149 AUDMIXSINKCMD_UNKNOWN = 0,
150 /** Enables the sink. */
151 AUDMIXSINKCMD_ENABLE,
152 /** Disables the sink. */
153 AUDMIXSINKCMD_DISABLE,
154 /** Pauses the sink. */
155 AUDMIXSINKCMD_PAUSE,
156 /** Resumes the sink. */
157 AUDMIXSINKCMD_RESUME,
158 /** Tells the sink's streams to drop all (buffered) data immediately. */
159 AUDMIXSINKCMD_DROP,
160 /** Hack to blow the type up to 32-bit. */
161 AUDMIXSINKCMD_32BIT_HACK = 0x7fffffff
162} AUDMIXSINKCMD;
163
164/**
165 * Audio input sink specifics.
166 *
167 * Do not use directly. Instead, use AUDMIXSINK.
168 */
169typedef struct AUDMIXSINKIN
170{
171 /** The current recording source. Can be NULL if not set. */
172 PAUDMIXSTREAM pStreamRecSource;
173} AUDMIXSINKIN;
174
175/**
176 * Audio output sink specifics.
177 *
178 * Do not use directly. Instead, use AUDMIXSINK.
179 */
180typedef struct AUDMIXSINKOUT
181{
182} AUDMIXSINKOUT;
183
184/**
185 * Audio mixer sink.
186 */
187typedef struct AUDMIXSINK
188{
189 RTLISTNODE Node;
190 /** Pointer to mixer object this sink is bound to. */
191 PAUDIOMIXER pParent;
192 /** Name of this sink. */
193 char *pszName;
194 /** The sink direction, that is,
195 * if this sink handles input or output. */
196 AUDMIXSINKDIR enmDir;
197 /** The sink's critical section. */
198 RTCRITSECT CritSect;
199 /** This sink's mixing buffer, acting as
200 * a parent buffer for all streams this sink owns. */
201 AUDIOMIXBUF MixBuf;
202 /** Scratch buffer for multiplexing / mixing. Might be NULL if not needed. */
203 uint8_t *pabScratchBuf;
204 /** Size (in bytes) of pabScratchBuf. Might be 0 if not needed. */
205 size_t cbScratchBuf;
206 /** Union for input/output specifics. */
207 union
208 {
209 AUDMIXSINKIN In;
210 AUDMIXSINKOUT Out;
211 };
212 /** Sink status of type AUDMIXSINK_STS_XXX. */
213 AUDMIXSINKSTS fStatus;
214 /** The sink's PCM format. */
215 PDMAUDIOPCMPROPS PCMProps;
216 /** Number of streams assigned. */
217 uint8_t cStreams;
218 /** List of assigned streams.
219 * @note All streams have the same PCM properties, so the mixer does not do
220 * any conversion. */
221 /** @todo Use something faster -- vector maybe? */
222 RTLISTANCHOR lstStreams;
223 /** The volume of this sink. The volume always will
224 * be combined with the mixer's master volume. */
225 PDMAUDIOVOLUME Volume;
226 /** The volume of this sink, combined with the last set master volume. */
227 PDMAUDIOVOLUME VolumeCombined;
228 /** Timestamp since last update (in ms). */
229 uint64_t tsLastUpdatedMs;
230 /** Last read (recording) / written (playback) timestamp (in ns). */
231 uint64_t tsLastReadWrittenNs;
232 struct
233 {
234 PAUDIOHLPFILE pFile;
235 } Dbg;
236} AUDMIXSINK;
237
238/**
239 * Audio mixer operation.
240 */
241typedef enum AUDMIXOP
242{
243 /** Invalid operation, do not use. */
244 AUDMIXOP_INVALID = 0,
245 /** Copy data from A to B, overwriting data in B. */
246 AUDMIXOP_COPY,
247 /** Blend data from A with (existing) data in B. */
248 AUDMIXOP_BLEND,
249 /** The usual 32-bit hack. */
250 AUDMIXOP_32BIT_HACK = 0x7fffffff
251} AUDMIXOP;
252
253/** No flags specified. */
254#define AUDMIXSTRMCTL_F_NONE 0
255
256/** No mixer flags specified. */
257#define AUDMIXER_FLAGS_NONE 0
258/** Debug mode enabled.
259 * This writes .WAV file to the host, usually to the temporary directory. */
260#define AUDMIXER_FLAGS_DEBUG RT_BIT(0)
261/** Validation mask. */
262#define AUDMIXER_FLAGS_VALID_MASK UINT32_C(0x00000001)
263
264int AudioMixerCreate(const char *pszName, uint32_t fFlags, PAUDIOMIXER *ppMixer);
265int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, AUDMIXSINKDIR enmDir, PPDMDEVINS pDevIns, PAUDMIXSINK *ppSink);
266void AudioMixerDestroy(PAUDIOMIXER pMixer, PPDMDEVINS pDevIns);
267void AudioMixerInvalidate(PAUDIOMIXER pMixer);
268void AudioMixerRemoveSink(PAUDIOMIXER pMixer, PAUDMIXSINK pSink);
269int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PPDMAUDIOVOLUME pVol);
270void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs);
271
272int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
273int AudioMixerSinkCreateStream(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PPDMAUDIOSTREAMCFG pCfg,
274 AUDMIXSTREAMFLAGS fFlags, PPDMDEVINS pDevIns, PAUDMIXSTREAM *ppStream);
275int AudioMixerSinkCtl(PAUDMIXSINK pSink, AUDMIXSINKCMD enmCmd);
276void AudioMixerSinkDestroy(PAUDMIXSINK pSink, PPDMDEVINS pDevIns);
277uint32_t AudioMixerSinkGetReadable(PAUDMIXSINK pSink);
278uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink);
279AUDMIXSINKDIR AudioMixerSinkGetDir(PAUDMIXSINK pSink);
280const char *AudioMixerSinkGetName(const PAUDMIXSINK pSink);
281PAUDMIXSTREAM AudioMixerSinkGetRecordingSource(PAUDMIXSINK pSink);
282PAUDMIXSTREAM AudioMixerSinkGetStream(PAUDMIXSINK pSink, uint8_t uIndex);
283AUDMIXSINKSTS AudioMixerSinkGetStatus(PAUDMIXSINK pSink);
284uint8_t AudioMixerSinkGetStreamCount(PAUDMIXSINK pSink);
285bool AudioMixerSinkIsActive(PAUDMIXSINK pSink);
286int AudioMixerSinkRead(PAUDMIXSINK pSink, AUDMIXOP enmOp, void *pvBuf, uint32_t cbBuf, uint32_t *pcbRead);
287void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
288void AudioMixerSinkRemoveAllStreams(PAUDMIXSINK pSink);
289void AudioMixerSinkReset(PAUDMIXSINK pSink);
290void AudioMixerSinkGetFormat(PAUDMIXSINK pSink, PPDMAUDIOPCMPROPS pPCMProps);
291int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PCPDMAUDIOPCMPROPS pPCMProps);
292int AudioMixerSinkSetRecordingSource(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
293int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PPDMAUDIOVOLUME pVol);
294int AudioMixerSinkWrite(PAUDMIXSINK pSink, AUDMIXOP enmOp, const void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
295int AudioMixerSinkUpdate(PAUDMIXSINK pSink);
296
297int AudioMixerStreamCtl(PAUDMIXSTREAM pStream, PDMAUDIOSTREAMCMD enmCmd, uint32_t fCtl);
298void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream, PPDMDEVINS pDevIns);
299bool AudioMixerStreamIsActive(PAUDMIXSTREAM pStream);
300bool AudioMixerStreamIsValid(PAUDMIXSTREAM pStream);
301
302#endif /* !VBOX_INCLUDED_SRC_Audio_AudioMixer_h */
303
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette