From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- src/VBox/Devices/Audio/AudioTest.h | 491 +++++++++++++++++++++++++++++++++++++ 1 file changed, 491 insertions(+) create mode 100644 src/VBox/Devices/Audio/AudioTest.h (limited to 'src/VBox/Devices/Audio/AudioTest.h') diff --git a/src/VBox/Devices/Audio/AudioTest.h b/src/VBox/Devices/Audio/AudioTest.h new file mode 100644 index 00000000..3dff6af2 --- /dev/null +++ b/src/VBox/Devices/Audio/AudioTest.h @@ -0,0 +1,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 . + * + * 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 */ + -- cgit v1.2.3