VirtualBox

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

Last change on this file since 89765 was 89371, checked in by vboxsync, 3 years ago

AudioMixer: More cleanups. bugref:9890

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

© 2023 Oracle
ContactPrivacy policyTerms of Use