1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
|
/* $Id: AudioTest.h $ */
/** @file
* Audio testing routines.
* Common code which is being used by the ValidationKit audio test (VKAT)
* and the debug / ValdikationKit audio driver(s).
*/
/*
* Copyright (C) 2021-2023 Oracle and/or its affiliates.
*
* This file is part of VirtualBox base platform packages, as
* available from https://www.virtualbox.org.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation, in version 3 of the
* License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses>.
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#ifndef VBOX_INCLUDED_SRC_Audio_AudioTest_h
#define VBOX_INCLUDED_SRC_Audio_AudioTest_h
#ifndef RT_WITHOUT_PRAGMA_ONCE
# pragma once
#endif
/** @todo Some stuff here can be private-only to the implementation. */
/** Maximum length in characters an audio test tag can have. */
#define AUDIOTEST_TAG_MAX 64
/** Maximum length in characters a single audio test error description can have. */
#define AUDIOTEST_ERROR_DESC_MAX 256
/** Prefix for audio test (set) directories. */
#define AUDIOTEST_PATH_PREFIX_STR "vkat"
/** Maximum tests a beacon can have.
* Maximum number of tests is 240 (so it can fit into 8-bit mono channels). */
#define AUDIOTEST_BEACON_TESTS_MAX 240
/** Returns a pre-beacon for a given test number.
* Maximum number of tests is 240 (so it can fit into 8-bit mono channels).
*
* That way it's easy to visually inspect beacon data in a hex editor --
* e.g. for test #5 a pre-beacon would be 0x5A + post-beacon 0x5B. */
#define AUDIOTEST_BEACON_MAKE_PRE(a_TstNum) \
( (uint8_t)((a_TstNum) & 0xf) << 4 \
| (uint8_t)(0xA))
/** Returns a post-beacon for a given test number.
* Maximum number of tests is 250 (so it can fit into 8-bit mono channels).
*
* That way it's easy to visually inspect beacon data in a hex editor --
* e.g. for test #2 a pre-beacon would be 0x2A + post-beacon 0x2B. */
#define AUDIOTEST_BEACON_MAKE_POST(a_TstNum) \
( (uint8_t)((a_TstNum) & 0xf) << 4 \
| (uint8_t)(0xB))
/** Pre / post audio beacon size (in audio frames). */
#define AUDIOTEST_BEACON_SIZE_FRAMES 1024
/**
* Enumeration for an audio test tone (wave) type.
*/
typedef enum AUDIOTESTTONETYPE
{
/** Invalid type. */
AUDIOTESTTONETYPE_INVALID = 0,
/** Sine wave. */
AUDIOTESTTONETYPE_SINE,
/** Square wave. Not implemented yet. */
AUDIOTESTTONETYPE_SQUARE,
/** Triangluar wave. Not implemented yet. */
AUDIOTESTTONETYPE_TRIANGLE,
/** Sawtooth wave. Not implemented yet. */
AUDIOTESTTONETYPE_SAWTOOTH,
/** The usual 32-bit hack. */
AUDIOTESTTONETYPE_32BIT_HACK = 0x7fffffff
} AUDIOTESTTONETYPE;
/**
* Structure for handling an audio (sine wave) test tone.
*/
typedef struct AUDIOTESTTONE
{
/** The tone's wave type. */
AUDIOTESTTONETYPE enmType;
/** The PCM properties. */
PDMAUDIOPCMPROPS Props;
/** Current sample index for generate the sine wave. */
uint64_t uSample;
/** The fixed portion of the sin() input. */
double rdFixed;
/** Frequency (in Hz) of the sine wave to generate. */
double rdFreqHz;
} AUDIOTESTTONE;
/** Pointer to an audio test tone. */
typedef AUDIOTESTTONE *PAUDIOTESTTONE;
/**
* Structure for a common test parameters header.
*/
typedef struct AUDIOTESTPARMSHDR
{
/** Test index these test parameters belong to.
* Set to UINT32_MAX if not being used. */
uint32_t idxTest;
/** Time of the caller when this test was being created. */
RTTIME tsCreated;
} AUDIOTESTPARMSHDR;
/** Pointer to an audio test tone. */
typedef AUDIOTESTPARMSHDR *PAUDIOTESTPARMSHDR;
/**
* Structure for handling audio test tone parameters.
*/
typedef struct AUDIOTESTTONEPARMS
{
/** Common test header. */
AUDIOTESTPARMSHDR Hdr;
/** The PCM properties. */
PDMAUDIOPCMPROPS Props;
/** Tone frequency (in Hz) to use.
* Will be later converted to a double value. */
double dbFreqHz;
/** Prequel (in ms) to play silence. Optional and can be set to 0. */
RTMSINTERVAL msPrequel;
/** Duration (in ms) to play the test tone. */
RTMSINTERVAL msDuration;
/** Sequel (in ms) to play silence. Optional and can be set to 0. */
RTMSINTERVAL msSequel;
/** Volume (in percent, 0-100) to use.
* If set to 0, the tone is muted (i.e. silent). */
uint8_t uVolumePercent;
} AUDIOTESTTONEPARMS;
/** Pointer to audio test tone parameters. */
typedef AUDIOTESTTONEPARMS *PAUDIOTESTTONEPARMS;
/**
* Enumeration defining an audio test beacon type.
*/
typedef enum AUDIOTESTTONEBEACONTYPE
{
/** Invalid type. */
AUDIOTESTTONEBEACONTYPE_INVALID = 0,
/** Playback beacon (pre). */
AUDIOTESTTONEBEACONTYPE_PLAY_PRE = 1,
/** Playback beacon (post). */
AUDIOTESTTONEBEACONTYPE_PLAY_POST = 2,
/** Recording beacon (pre). */
AUDIOTESTTONEBEACONTYPE_REC_PRE = 3,
/** Recording beacon (post). */
AUDIOTESTTONEBEACONTYPE_REC_POST = 4,
/** The usual 32-bit hack. */
OTESTTONEBEACONTYPE_32BIT_HACK = 0x7fffffff
} AUDIOTESTTONEBEACONTYPE;
/**
* Structure defining an audio test tone beacon.
*
* This is being used for (optionally) marking beginning/ending of audio test data.
*/
typedef struct AUDIOTESTTONEBEACON
{
/** Test number this beacon is for. */
uint8_t uTest;
/** The beacon type. */
AUDIOTESTTONEBEACONTYPE enmType;
/** PCM properties to use for this beacon. */
PDMAUDIOPCMPROPS Props;
/** Beacon bytes to process.
* When doing test tone playback: Beacon bytes to write.
* When doing test tone recording: Beacon bytes to read. */
uint32_t cbSize;
/** Beacon bytes already processed.
* When doing test tone playback: Beacon bytes written.
* When doing test tone recording: Beacon bytes read. */
uint32_t cbUsed;
} AUDIOTESTTONEBEACON;
/** Pointer to audio test tone beacon. */
typedef AUDIOTESTTONEBEACON *PAUDIOTESTTONEBEACON;
/** Pointer (const) to audio test tone beacon. */
typedef AUDIOTESTTONEBEACON const *PCAUDIOTESTTONEBEACON;
/**
* Enumeration for the test set mode.
*/
typedef enum AUDIOTESTSETMODE
{
/** Invalid test set mode. */
AUDIOTESTSETMODE_INVALID = 0,
/** Test set is being created (testing in progress). */
AUDIOTESTSETMODE_TEST,
/** Existing test set is being verified. */
AUDIOTESTSETMODE_VERIFY,
/** The usual 32-bit hack. */
AUDIOTESTSETMODE_32BIT_HACK = 0x7fffffff
} AUDIOTESTSETMODE;
/**
* Enumeration to specify an audio test type.
*/
typedef enum AUDIOTESTTYPE
{
/** Invalid test type, do not use. */
AUDIOTESTTYPE_INVALID = 0,
/** Play a test tone. */
AUDIOTESTTYPE_TESTTONE_PLAY,
/** Record a test tone. */
AUDIOTESTTYPE_TESTTONE_RECORD,
/** The usual 32-bit hack. */
AUDIOTESTTYPE_32BIT_HACK = 0x7fffffff
} AUDIOTESTTYPE;
/**
* Audio test request data.
*/
typedef struct AUDIOTESTPARMS
{
/** Audio device to use. */
PDMAUDIOHOSTDEV Dev;
/** How much to delay (wait, in ms) the test being executed. */
RTMSINTERVAL msDelay;
/** The test direction. */
PDMAUDIODIR enmDir;
/** The test type. */
AUDIOTESTTYPE enmType;
/** Union for test type-specific data. */
union
{
AUDIOTESTTONEPARMS TestTone;
};
} AUDIOTESTPARMS;
/** Pointer to a test parameter structure. */
typedef AUDIOTESTPARMS *PAUDIOTESTPARMS;
/** Test object handle. */
typedef R3R0PTRTYPE(struct AUDIOTESTOBJINT RT_FAR *) AUDIOTESTOBJ;
/** Pointer to test object handle. */
typedef AUDIOTESTOBJ RT_FAR *PAUDIOTESTOBJ;
/** Nil test object handle. */
#define NIL_AUDIOTESTOBJ ((AUDIOTESTOBJ)~(RTHCINTPTR)0)
struct AUDIOTESTSET;
/**
* Structure specifying a single audio test entry of a test set.
*
* A test set can contain zero or more test entry (tests).
*/
typedef struct AUDIOTESTENTRY
{
/** List node. */
RTLISTNODE Node;
/** Pointer to test set parent. */
AUDIOTESTSET *pParent;
/** Friendly description of the test. */
char szDesc[64];
/** Audio test parameters this test needs to perform the actual test. */
AUDIOTESTPARMS Parms;
/** Number of test objects bound to this test. */
uint32_t cObj;
/** Absolute offset (in bytes) where to write the "obj_count" value later. */
uint64_t offObjCount;
/** Overall test result. */
int rc;
} AUDIOTESTENTRY;
/** Pointer to an audio test entry. */
typedef AUDIOTESTENTRY *PAUDIOTESTENTRY;
/**
* Structure specifying an audio test set.
*/
typedef struct AUDIOTESTSET
{
/** The set's tag. */
char szTag[AUDIOTEST_TAG_MAX];
/** Absolute path where to store the test audio data. */
char szPathAbs[RTPATH_MAX];
/** Current mode the test set is in. */
AUDIOTESTSETMODE enmMode;
union
{
/** @todo r=bird: RTSTREAM not RTFILE. That means you don't have to check
* every write status code and it's buffered and thus faster. Also,
* you don't have to re-invent fprintf-style RTFileWrite wrappers. */
RTFILE hFile;
RTINIFILE hIniFile;
} f;
/** Number of test objects in lstObj. */
uint32_t cObj;
/** Absolute offset (in bytes) where to write the "obj_count" value later. */
uint64_t offObjCount;
/** List containing PAUDIOTESTOBJ test object entries. */
RTLISTANCHOR lstObj;
/** Number of performed tests.
* Not necessarily bound to the test object entries above. */
uint32_t cTests;
/** Absolute offset (in bytes) where to write the "test_count" value later. */
uint64_t offTestCount;
/** List containing PAUDIOTESTENTRY test entries. */
RTLISTANCHOR lstTest;
/** Current test running. Can be NULL if no test is running. */
PAUDIOTESTENTRY pTestCur;
/** Number of tests currently running.
* Currently we only allow one concurrent test running at a given time. */
uint32_t cTestsRunning;
/** Number of total (test) failures. */
uint32_t cTotalFailures;
} AUDIOTESTSET;
/** Pointer to an audio test set. */
typedef AUDIOTESTSET *PAUDIOTESTSET;
/**
* Audio test verification options.
*/
typedef struct AUDIOTESTVERIFYOPTS
{
/** Flag indicating whether to keep going after an error has occurred. */
bool fKeepGoing;
/** Whether to perform audio normalization or not. */
bool fNormalize;
/** Threshold of file differences (number of chunks) at when we consider audio files
* as not matching. 0 means an exact match. */
uint32_t cMaxDiff;
/** Threshold of file differences (difference in percent) at when we consider audio files
* as not matching. 0 means an exact match. */
uint8_t uMaxDiffPercent;
/** Threshold of file size (+/-, in percent) at when we consider audio files
* as not matching. 0 means an exact match.*/
uint8_t uMaxSizePercent;
/** Search window (in ms) to use for treating / classifying audio data. */
uint32_t msSearchWindow;
} AUDIOTESTVERIFYOPTS;
/** Pointer to audio test verification options. */
typedef AUDIOTESTVERIFYOPTS *PAUDIOTESTVERIFYOPTS;
/**
* Structure for holding a single audio test error entry.
*/
typedef struct AUDIOTESTERRORENTRY
{
/** The entrie's list node. */
RTLISTNODE Node;
/** Additional rc. */
int rc;
/** Actual error description. */
char szDesc[AUDIOTEST_ERROR_DESC_MAX];
} AUDIOTESTERRORENTRY;
/** Pointer to an audio test error description. */
typedef AUDIOTESTERRORENTRY *PAUDIOTESTERRORENTRY;
/**
* Structure for holding an audio test error description.
* This can contain multiple errors (FIFO list).
*/
typedef struct AUDIOTESTERRORDESC
{
/** List entries containing the (FIFO-style) errors of type AUDIOTESTERRORENTRY. */
RTLISTANCHOR List;
/** Number of errors in the list. */
uint32_t cErrors;
} AUDIOTESTERRORDESC;
/** Pointer to an audio test error description. */
typedef AUDIOTESTERRORDESC *PAUDIOTESTERRORDESC;
/** Const pointer to an audio test error description. */
typedef AUDIOTESTERRORDESC const *PCAUDIOTESTERRORDESC;
/**
* Enumeration specifying an internal test state.
*/
typedef enum AUDIOTESTSTATE
{
/** Test is initializing. */
AUDIOTESTSTATE_INIT = 0,
/** Test is in pre-run phase. */
AUDIOTESTSTATE_PRE,
/** Test is running */
AUDIOTESTSTATE_RUN,
/** Test is in post-run phase. */
AUDIOTESTSTATE_POST,
/** Test has been run. */
AUDIOTESTSTATE_DONE,
/** The usual 32-bit hack. */
AUDIOTESTSTATE_32BIT_HACK = 0x7fffffff
} AUDIOTESTSTATE;
double AudioTestToneInit(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps, double dbFreq);
double AudioTestToneInitRandom(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps);
double AudioTestToneGetRandomFreq(void);
int AudioTestToneGenerate(PAUDIOTESTTONE pTone, void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
void AudioTestBeaconInit(PAUDIOTESTTONEBEACON pBeacon, uint8_t uTest, AUDIOTESTTONEBEACONTYPE enmType, PPDMAUDIOPCMPROPS pProps);
int AudioTestBeaconAddConsecutive(PAUDIOTESTTONEBEACON pBeacon, const uint8_t *auBuf, size_t cbBuf, size_t *pOff);
int AudioTestBeaconWrite(PAUDIOTESTTONEBEACON pBeacon, void *pvBuf, uint32_t cbBuf);
uint32_t AudioTestBeaconGetSize(PCAUDIOTESTTONEBEACON pBeacon);
const char *AudioTestBeaconTypeGetName(AUDIOTESTTONEBEACONTYPE enmType);
AUDIOTESTTONEBEACONTYPE AudioTestBeaconGetType(PCAUDIOTESTTONEBEACON pBeacon);
uint32_t AudioTestBeaconGetRemaining(PCAUDIOTESTTONEBEACON pBeacon);
uint32_t AudioTestBeaconGetUsed(PCAUDIOTESTTONEBEACON pBeacon);
bool AudioTestBeaconIsComplete(PCAUDIOTESTTONEBEACON pBeacon);
int AudioTestGenTag(char *pszTag, size_t cbTag);
int AudioTestPathGetTemp(char *pszPath, size_t cbPath);
int AudioTestPathCreateTemp(char *pszPath, size_t cbPath, const char *pszUUID);
int AudioTestPathCreate(char *pszPath, size_t cbPath, const char *pszUUID);
int AudioTestSetObjCreateAndRegister(PAUDIOTESTSET pSet, const char *pszName, PAUDIOTESTOBJ pObj);
int AudioTestObjWrite(AUDIOTESTOBJ Obj, const void *pvBuf, size_t cbBuf);
int AudioTestObjAddMetadataStr(AUDIOTESTOBJ Obj, const char *pszFormat, ...);
int AudioTestObjClose(AUDIOTESTOBJ Obj);
int AudioTestSetTestBegin(PAUDIOTESTSET pSet, const char *pszDesc, PAUDIOTESTPARMS pParms, PAUDIOTESTENTRY *ppEntry);
int AudioTestSetTestFailed(PAUDIOTESTENTRY pEntry, int rc, const char *pszErr);
int AudioTestSetTestDone(PAUDIOTESTENTRY pEntry);
bool AudioTestSetTestIsRunning(PAUDIOTESTENTRY pEntry);
int AudioTestSetCreate(PAUDIOTESTSET pSet, const char *pszPath, const char *pszTag);
int AudioTestSetDestroy(PAUDIOTESTSET pSet);
int AudioTestSetOpen(PAUDIOTESTSET pSet, const char *pszPath);
int AudioTestSetClose(PAUDIOTESTSET pSet);
int AudioTestSetWipe(PAUDIOTESTSET pSet);
const char *AudioTestSetGetTag(PAUDIOTESTSET pSet);
uint32_t AudioTestSetGetTestsTotal(PAUDIOTESTSET pSet);
uint32_t AudioTestSetGetTestsRunning(PAUDIOTESTSET pSet);
uint32_t AudioTestSetGetTotalFailures(PAUDIOTESTSET pSet);
bool AudioTestSetIsPacked(const char *pszPath);
bool AudioTestSetIsRunning(PAUDIOTESTSET pSet);
int AudioTestSetPack(PAUDIOTESTSET pSet, const char *pszOutDir, char *pszFileName, size_t cbFileName);
int AudioTestSetUnpack(const char *pszFile, const char *pszOutDir);
void AudioTestSetVerifyOptsInitStrict(PAUDIOTESTVERIFYOPTS pOpts);
void AudioTestSetVerifyOptsInit(PAUDIOTESTVERIFYOPTS pOpts);
bool AudioTestSetVerifyOptsAreEqual(PAUDIOTESTVERIFYOPTS pOptsA, PAUDIOTESTVERIFYOPTS pOptsB);
int AudioTestSetVerify(PAUDIOTESTSET pSetA, PAUDIOTESTSET pSetB, PAUDIOTESTERRORDESC pErrDesc);
int AudioTestSetVerifyEx(PAUDIOTESTSET pSetA, PAUDIOTESTSET pSetB, PAUDIOTESTVERIFYOPTS pOpts, PAUDIOTESTERRORDESC pErrDesc);
uint32_t AudioTestErrorDescCount(PCAUDIOTESTERRORDESC pErr);
bool AudioTestErrorDescFailed(PCAUDIOTESTERRORDESC pErr);
void AudioTestErrorDescDestroy(PAUDIOTESTERRORDESC pErr);
const char *AudioTestStateToStr(AUDIOTESTSTATE enmState);
/** @name Wave File Accessors
* @{ */
/**
* An open wave (.WAV) file.
*/
typedef struct AUDIOTESTWAVEFILE
{
/** Magic value (AUDIOTESTWAVEFILE_MAGIC). */
uint32_t u32Magic;
/** Set if we're in read-mode, clear if in write mode. */
bool fReadMode;
/** The file handle. */
RTFILE hFile;
/** The absolute file offset of the first sample */
uint32_t offSamples;
/** Number of bytes of samples. */
uint32_t cbSamples;
/** The current read position relative to @a offSamples. */
uint32_t offCur;
/** The PCM properties for the file format. */
PDMAUDIOPCMPROPS Props;
} AUDIOTESTWAVEFILE;
/** Pointer to an open wave file. */
typedef AUDIOTESTWAVEFILE *PAUDIOTESTWAVEFILE;
/** Magic value for AUDIOTESTWAVEFILE::u32Magic (Miles Dewey Davis III). */
#define AUDIOTESTWAVEFILE_MAGIC UINT32_C(0x19260526)
/** Magic value for AUDIOTESTWAVEFILE::u32Magic after closing. */
#define AUDIOTESTWAVEFILE_MAGIC_DEAD UINT32_C(0x19910928)
int AudioTestWaveFileOpen(const char *pszFile, PAUDIOTESTWAVEFILE pWaveFile, PRTERRINFO pErrInfo);
int AudioTestWaveFileCreate(const char *pszFile, PCPDMAUDIOPCMPROPS pProps, PAUDIOTESTWAVEFILE pWaveFile, PRTERRINFO pErrInfo);
int AudioTestWaveFileRead(PAUDIOTESTWAVEFILE pWaveFile, void *pvBuf, size_t cbBuf, size_t *pcbRead);
int AudioTestWaveFileWrite(PAUDIOTESTWAVEFILE pWaveFile, const void *pvBuf, size_t cbBuf);
int AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile);
/** @} */
#endif /* !VBOX_INCLUDED_SRC_Audio_AudioTest_h */
|