VirtualBox

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

Last change on this file since 89351 was 89332, checked in by vboxsync, 4 years ago

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