VirtualBox

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

Last change on this file since 90778 was 89810, checked in by vboxsync, 3 years ago

Audio: Eliminated some unnecessary stream config copying in the device code. bugref:9890

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

© 2023 Oracle
ContactPrivacy policyTerms of Use