VirtualBox

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

Last change on this file since 98638 was 98456, checked in by vboxsync, 23 months ago

Audio: Backed out r155649 + r155650, as this needs another approach. The three device emulations are too different wrt locking and stream setup / teardown when it comes to if and when they reset their DMA buffers. Needs more testing first. bugref:10354

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.8 KB
Line 
1/* $Id: AudioMixer.h 98456 2023-02-02 20:23: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-2023 Oracle and/or its affiliates.
11 *
12 * This file is part of VirtualBox base platform packages, as
13 * available from https://www.virtualbox.org.
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation, in version 3 of the
18 * License.
19 *
20 * This program is distributed in the hope that it will be useful, but
21 * WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, see <https://www.gnu.org/licenses>.
27 *
28 * SPDX-License-Identifier: GPL-3.0-only
29 */
30
31#ifndef VBOX_INCLUDED_SRC_Audio_AudioMixer_h
32#define VBOX_INCLUDED_SRC_Audio_AudioMixer_h
33#ifndef RT_WITHOUT_PRAGMA_ONCE
34# pragma once
35#endif
36
37#include <iprt/cdefs.h>
38#include <iprt/critsect.h>
39
40#include <VBox/vmm/pdmaudioifs.h>
41#include "AudioMixBuffer.h"
42#include "AudioHlp.h"
43
44
45/** @defgroup grp_pdm_ifs_audio_mixing Audio Mixing
46 * @ingroup grp_pdm_ifs_audio
47 *
48 * @note This is currently placed under PDM Audio Interface as that seemed like
49 * the best place for it.
50 *
51 * @{
52 */
53
54/** Pointer to an audio mixer sink. */
55typedef struct AUDMIXSINK *PAUDMIXSINK;
56/** Pointer to a const audio mixer sink. */
57typedef struct AUDMIXSINK const *PCAUDMIXSINK;
58
59
60/**
61 * Audio mixer instance.
62 */
63typedef struct AUDIOMIXER
64{
65 /** Magic value (AUDIOMIXER_MAGIC). */
66 uintptr_t uMagic;
67 /** The mixer's name (allocated after this structure). */
68 char const *pszName;
69 /** The master volume of this mixer. */
70 PDMAUDIOVOLUME VolMaster;
71 /** List of audio mixer sinks (AUDMIXSINK). */
72 RTLISTANCHOR lstSinks;
73 /** Number of used audio sinks. */
74 uint8_t cSinks;
75 /** Mixer flags. See AUDMIXER_FLAGS_XXX. */
76 uint32_t fFlags;
77 /** The mixer's critical section. */
78 RTCRITSECT CritSect;
79} AUDIOMIXER;
80/** Pointer to an audio mixer instance. */
81typedef AUDIOMIXER *PAUDIOMIXER;
82
83/** Value for AUDIOMIXER::uMagic. (Attilio Joseph "Teo" Macero) */
84#define AUDIOMIXER_MAGIC UINT32_C(0x19251030)
85/** Value for AUDIOMIXER::uMagic after destruction. */
86#define AUDIOMIXER_MAGIC_DEAD UINT32_C(0x20080219)
87
88/** @name AUDMIXER_FLAGS_XXX - For AudioMixerCreate().
89 * @{ */
90/** No mixer flags specified. */
91#define AUDMIXER_FLAGS_NONE 0
92/** Debug mode enabled.
93 * This writes .WAV file to the host, usually to the temporary directory. */
94#define AUDMIXER_FLAGS_DEBUG RT_BIT(0)
95/** Validation mask. */
96#define AUDMIXER_FLAGS_VALID_MASK UINT32_C(0x00000001)
97/** @} */
98
99
100/**
101 * Audio mixer stream.
102 */
103typedef struct AUDMIXSTREAM
104{
105 /** List entry on AUDMIXSINK::lstStreams. */
106 RTLISTNODE Node;
107 /** Magic value (AUDMIXSTREAM_MAGIC). */
108 uint32_t uMagic;
109 /** The backend buffer size in frames (for draining deadline calc). */
110 uint32_t cFramesBackendBuffer;
111 /** Stream status of type AUDMIXSTREAM_STATUS_. */
112 uint32_t fStatus;
113 /** Number of writable/readable frames the last time we checked. */
114 uint32_t cFramesLastAvail;
115 /** Set if the stream has been found unreliable wrt. consuming/producing
116 * samples, and that we shouldn't consider it when deciding how much to move
117 * from the mixer buffer and to the drivers. */
118 bool fUnreliable;
119 /** Name of this stream. */
120 char *pszName;
121 /** The statistics prefix. */
122 char *pszStatPrefix;
123 /** Sink this stream is attached to. */
124 PAUDMIXSINK pSink;
125 /** Pointer to audio connector being used. */
126 PPDMIAUDIOCONNECTOR pConn;
127 /** Pointer to PDM audio stream this mixer stream handles. */
128 PPDMAUDIOSTREAM pStream;
129 union
130 {
131 /** Output: Mixing buffer peeking state & config. */
132 AUDIOMIXBUFPEEKSTATE PeekState;
133 /** Input: Mixing buffer writing state & config. */
134 AUDIOMIXBUFWRITESTATE WriteState;
135 };
136 /** Last read (recording) / written (playback) timestamp (in ns). */
137 uint64_t tsLastReadWrittenNs;
138 /** The streams's critical section. */
139 RTCRITSECT CritSect;
140} AUDMIXSTREAM;
141/** Pointer to an audio mixer stream. */
142typedef AUDMIXSTREAM *PAUDMIXSTREAM;
143
144/** Value for AUDMIXSTREAM::uMagic. (Jan Erik Kongshaug) */
145#define AUDMIXSTREAM_MAGIC UINT32_C(0x19440704)
146/** Value for AUDMIXSTREAM::uMagic after destruction. */
147#define AUDMIXSTREAM_MAGIC_DEAD UINT32_C(0x20191105)
148
149
150/** @name AUDMIXSTREAM_STATUS_XXX - mixer stream status.
151 * (This is a destilled version of PDMAUDIOSTREAM_STS_XXX.)
152 * @{ */
153/** No status set. */
154#define AUDMIXSTREAM_STATUS_NONE UINT32_C(0)
155/** The mixing stream is enabled (active). */
156#define AUDMIXSTREAM_STATUS_ENABLED RT_BIT_32(0)
157/** The mixing stream can be read from.
158 * Always set together with AUDMIXSTREAM_STATUS_ENABLED. */
159#define AUDMIXSTREAM_STATUS_CAN_READ RT_BIT_32(1)
160/** The mixing stream can be written to.
161 * Always set together with AUDMIXSTREAM_STATUS_ENABLED. */
162#define AUDMIXSTREAM_STATUS_CAN_WRITE RT_BIT_32(2)
163/** @} */
164
165
166/** Callback for an asynchronous I/O update job. */
167typedef DECLCALLBACKTYPE(void, FNAUDMIXSINKUPDATE,(PPDMDEVINS pDevIns, PAUDMIXSINK pSink, void *pvUser));
168/** Pointer to a callback for an asynchronous I/O update job. */
169typedef FNAUDMIXSINKUPDATE *PFNAUDMIXSINKUPDATE;
170
171/**
172 * Audio mixer sink.
173 */
174typedef struct AUDMIXSINK
175{
176 /** List entry on AUDIOMIXER::lstSinks. */
177 RTLISTNODE Node;
178 /** Magic value (AUDMIXSINK_MAGIC). */
179 uint32_t uMagic;
180 /** The sink direction (either PDMAUDIODIR_IN or PDMAUDIODIR_OUT). */
181 PDMAUDIODIR enmDir;
182 /** Pointer to mixer object this sink is bound to. */
183 PAUDIOMIXER pParent;
184 /** Name of this sink (allocated after this structure). */
185 char const *pszName;
186 /** The sink's PCM format (i.e. the guest device side). */
187 PDMAUDIOPCMPROPS PCMProps;
188 /** Sink status bits - AUDMIXSINK_STS_XXX. */
189 uint32_t fStatus;
190 /** Number of bytes to be transferred from the device DMA buffer before the
191 * streams will be put into draining mode. */
192 uint32_t cbDmaLeftToDrain;
193 /** The deadline for draining if it's pending. */
194 uint64_t nsDrainDeadline;
195 /** When the draining startet (for logging). */
196 uint64_t nsDrainStarted;
197 /** Number of streams assigned. */
198 uint8_t cStreams;
199 /** List of assigned streams (AUDMIXSTREAM).
200 * @note All streams have the same PCM properties, so the mixer does not do
201 * any conversion. bird: That is *NOT* true any more, the mixer has
202 * encoders/decoder states for each stream (well, input is still a todo).
203 *
204 * @todo Use something faster -- vector maybe? bird: It won't be faster. You
205 * will have a vector of stream pointers (because you cannot have a vector
206 * of full AUDMIXSTREAM structures since they'll move when the vector is
207 * reallocated and we need pointers to them to give out to devices), which
208 * is the same cost as going via Node.pNext/pPrev. */
209 RTLISTANCHOR lstStreams;
210 /** The volume of this sink. The volume always will
211 * be combined with the mixer's master volume. */
212 PDMAUDIOVOLUME Volume;
213 /** The volume of this sink, combined with the last set master volume. */
214 PDMAUDIOVOLUME VolumeCombined;
215 /** Timestamp since last update (in ms). */
216 uint64_t tsLastUpdatedMs;
217 /** Last read (recording) / written (playback) timestamp (in ns). */
218 uint64_t tsLastReadWrittenNs;
219 /** Union for input/output specifics. */
220 union
221 {
222 struct
223 {
224 /** The sink's peek state. */
225 AUDIOMIXBUFPEEKSTATE State;
226 } In;
227 struct
228 {
229 /** The sink's write state. */
230 AUDIOMIXBUFWRITESTATE State;
231 } Out;
232 };
233 struct
234 {
235 PAUDIOHLPFILE pFile;
236 } Dbg;
237 /** This sink's mixing buffer. */
238 AUDIOMIXBUF MixBuf;
239 /** Asynchronous I/O thread related stuff. */
240 struct
241 {
242 /** The thread handle, NIL_RTTHREAD if not active. */
243 RTTHREAD hThread;
244 /** Event for letting the thread know there is some data to process. */
245 RTSEMEVENT hEvent;
246 /** The device instance (same for all update jobs). */
247 PPDMDEVINS pDevIns;
248 /** Started indicator. */
249 volatile bool fStarted;
250 /** Shutdown indicator. */
251 volatile bool fShutdown;
252 /** Number of update jobs this sink has (usually zero or one). */
253 uint8_t cUpdateJobs;
254 /** The minimum typical interval for all jobs. */
255 uint32_t cMsMinTypicalInterval;
256 /** Update jobs for this sink. */
257 struct
258 {
259 /** User specific argument. */
260 void *pvUser;
261 /** The callback. */
262 PFNAUDMIXSINKUPDATE pfnUpdate;
263 /** Typical interval in milliseconds. */
264 uint32_t cMsTypicalInterval;
265 } aUpdateJobs[8];
266 } AIO;
267 /** The sink's critical section. */
268 RTCRITSECT CritSect;
269} AUDMIXSINK;
270
271/** Value for AUDMIXSINK::uMagic. (Sir George Martin) */
272#define AUDMIXSINK_MAGIC UINT32_C(0x19260103)
273/** Value for AUDMIXSINK::uMagic after destruction. */
274#define AUDMIXSINK_MAGIC_DEAD UINT32_C(0x20160308)
275
276
277/** @name AUDMIXSINK_STS_XXX - Sink status bits.
278 * @{ */
279/** No status specified. */
280#define AUDMIXSINK_STS_NONE 0
281/** The sink is active and running. */
282#define AUDMIXSINK_STS_RUNNING RT_BIT(0)
283/** Draining the buffers and pending stop - output only. */
284#define AUDMIXSINK_STS_DRAINING RT_BIT(1)
285/** Drained the DMA buffer. */
286#define AUDMIXSINK_STS_DRAINED_DMA RT_BIT(2)
287/** Drained the mixer buffer, only waiting for streams (drivers) now. */
288#define AUDMIXSINK_STS_DRAINED_MIXBUF RT_BIT(3)
289/** Dirty flag.
290 * - For output sinks this means that there is data in the sink which has not
291 * been played yet.
292 * - For input sinks this means that there is data in the sink which has been
293 * recorded but not transferred to the destination yet.
294 * @todo This isn't used for *anything* at the moment. Remove? */
295#define AUDMIXSINK_STS_DIRTY RT_BIT(4)
296/** @} */
297
298
299/** @name Audio mixer methods
300 * @{ */
301int AudioMixerCreate(const char *pszName, uint32_t fFlags, PAUDIOMIXER *ppMixer);
302void AudioMixerDestroy(PAUDIOMIXER pMixer, PPDMDEVINS pDevIns);
303void AudioMixerDebug(PAUDIOMIXER pMixer, PCDBGFINFOHLP pHlp, const char *pszArgs);
304int AudioMixerSetMasterVolume(PAUDIOMIXER pMixer, PCPDMAUDIOVOLUME pVol);
305int AudioMixerCreateSink(PAUDIOMIXER pMixer, const char *pszName, PDMAUDIODIR enmDir, PPDMDEVINS pDevIns, PAUDMIXSINK *ppSink);
306/** @} */
307
308/** @name Audio mixer sink methods
309 * @{ */
310int AudioMixerSinkStart(PAUDMIXSINK pSink);
311int AudioMixerSinkDrainAndStop(PAUDMIXSINK pSink, uint32_t cbComming);
312void AudioMixerSinkDestroy(PAUDMIXSINK pSink, PPDMDEVINS pDevIns);
313uint32_t AudioMixerSinkGetReadable(PAUDMIXSINK pSink);
314uint32_t AudioMixerSinkGetWritable(PAUDMIXSINK pSink);
315PDMAUDIODIR AudioMixerSinkGetDir(PCAUDMIXSINK pSink);
316uint32_t AudioMixerSinkGetStatus(PAUDMIXSINK pSink);
317bool AudioMixerSinkIsActive(PAUDMIXSINK pSink);
318void AudioMixerSinkReset(PAUDMIXSINK pSink);
319int AudioMixerSinkSetFormat(PAUDMIXSINK pSink, PCPDMAUDIOPCMPROPS pPCMProps, uint32_t cMsSchedulingHint);
320int AudioMixerSinkSetVolume(PAUDMIXSINK pSink, PCPDMAUDIOVOLUME pVol);
321int AudioMixerSinkUpdate(PAUDMIXSINK pSink, uint32_t cbDmaUsed, uint32_t cbDmaPeriod);
322
323int AudioMixerSinkAddUpdateJob(PAUDMIXSINK pSink, PFNAUDMIXSINKUPDATE pfnUpdate, void *pvUser, uint32_t cMsTypicalInterval);
324int AudioMixerSinkRemoveUpdateJob(PAUDMIXSINK pSink, PFNAUDMIXSINKUPDATE pfnUpdate, void *pvUser);
325int AudioMixerSinkSignalUpdateJob(PAUDMIXSINK pSink);
326uint64_t AudioMixerSinkTransferFromCircBuf(PAUDMIXSINK pSink, PRTCIRCBUF pCircBuf, uint64_t offStream,
327 uint32_t idStream, PAUDIOHLPFILE pDbgFile);
328uint64_t AudioMixerSinkTransferToCircBuf(PAUDMIXSINK pSink, PRTCIRCBUF pCircBuf, uint64_t offStream,
329 uint32_t idStream, PAUDIOHLPFILE pDbgFile);
330int AudioMixerSinkLock(PAUDMIXSINK pSink);
331int AudioMixerSinkTryLock(PAUDMIXSINK pSink);
332int AudioMixerSinkUnlock(PAUDMIXSINK pSink);
333
334int AudioMixerSinkCreateStream(PAUDMIXSINK pSink, PPDMIAUDIOCONNECTOR pConnector, PCPDMAUDIOSTREAMCFG pCfg,
335 PPDMDEVINS pDevIns, PAUDMIXSTREAM *ppStream);
336int AudioMixerSinkAddStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
337void AudioMixerSinkRemoveStream(PAUDMIXSINK pSink, PAUDMIXSTREAM pStream);
338void AudioMixerSinkRemoveAllStreams(PAUDMIXSINK pSink);
339/** @} */
340
341/** @name Audio mixer stream methods
342 * @{ */
343void AudioMixerStreamDestroy(PAUDMIXSTREAM pStream, PPDMDEVINS pDevIns, bool fImmediate);
344/** @} */
345
346/** @} */
347
348#endif /* !VBOX_INCLUDED_SRC_Audio_AudioMixer_h */
349
Note: See TracBrowser for help on using the repository browser.

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