VirtualBox

Changeset 90046 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jul 6, 2021 9:03:18 AM (3 years ago)
Author:
vboxsync
Message:

Audio/ValKit: More code for PCM audio data test (set) verification. bugref:10008

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/AudioTest.cpp

    r90005 r90046  
    4444#define _USE_MATH_DEFINES
    4545#include <math.h> /* sin, M_PI */
     46
     47#define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO /** @todo Add an own log group for this? */
     48#include <VBox/log.h>
    4649
    4750#include <VBox/version.h>
     
    181184    /** Flag indicating whether to keep going after an error has occurred. */
    182185    bool                fKeepGoing;
     186    /** Threshold of file differences (chunks) at when we consider audio files
     187     *  as not matching. */
     188    uint32_t            cThresholdDiff;
    183189    /** PCM properties to use for verification. */
    184190    PDMAUDIOPCMPROPS    PCMProps;
     
    376382
    377383/**
     384 * Finds the next audible *or* silent audio sample and returns its offset.
     385 *
     386 * @returns Offset (in bytes) of the next found sample.
     387 * @param   hFile               File handle of file to search in.
     388 * @param   fFindSilence        Whether to search for a silent sample or not (i.e. audible).
     389 *                              What a silent sample is depends on \a pToneParms PCM parameters.
     390 * @param   uOff                Absolute offset (in bytes) to start searching from.
     391 * @param   pToneParms          Tone parameters to use.
     392 */
     393static uint64_t audioTestToneFileFind(RTFILE hFile, bool fFindSilence, uint64_t uOff, PAUDIOTESTTONEPARMS pToneParms)
     394{
     395    int rc = RTFileSeek(hFile, uOff, RTFILE_SEEK_BEGIN, NULL);
     396    AssertRCReturn(rc, 0);
     397
     398    uint64_t offFound       = 0;
     399    int64_t  abSample[_4K];
     400
     401    size_t   cbRead;
     402    uint32_t cConseqSilence = 0;
     403    for (;;)
     404    {
     405        rc = RTFileRead(hFile, &abSample, sizeof(abSample), &cbRead);
     406        if (   RT_FAILURE(rc)
     407            || !cbRead)
     408            break;
     409
     410        size_t const cbSample = PDMAudioPropsSampleSize(&pToneParms->Props);
     411
     412        for (size_t i = 0; i < cbRead / cbSample; i += cbSample) /** @todo Slow as heck, but works for now. */
     413        {
     414            bool const fIsSilence = PDMAudioPropsIsBufferSilence(&pToneParms->Props, (const uint8_t *)abSample + i, cbSample);
     415            if (fIsSilence == fFindSilence)
     416            {
     417                offFound += cbSample;
     418                cConseqSilence++;
     419            }
     420            else
     421                break;
     422        }
     423    }
     424
     425    return offFound;
     426}
     427
     428/**
    378429 * Generates a tag.
    379430 *
     
    801852    int rc = audioTestObjGetStr(phObj, pszKey, szVal, sizeof(szVal));
    802853    if (RT_SUCCESS(rc))
    803         *pbVal = RT_BOOL(RTStrToUInt8(szVal));
     854        *pbVal =    (RTStrICmp(szVal, "true") == 0)
     855                 || (RTStrICmp(szVal, "1")    == 0) ? true : false;
    804856
    805857    return rc;
     
    18401892{
    18411893    int rc;
    1842 
    18431894    uint32_t uHz;
    18441895    rc = audioTestObjGetUInt32(phObj, "tone_pcm_hz", &uHz);
     
    18601911
    18611912/**
    1862  * Compares two (binary) files.
    1863  *
    1864  * @returns \c true if equal, or \c false if not.
    1865  * @param   hFileA              File handle to file A to compare.
    1866  * @param   hFileB              File handle to file B to compare file A with.
    1867  * @param   cbToCompare         Number of bytes to compare starting the the both file's
    1868  *                              current position.
    1869  */
    1870 static bool audioTestFilesCompareBinary(RTFILE hFileA, RTFILE hFileB, uint64_t cbToCompare)
    1871 {
    1872     uint8_t auBufA[_32K];
    1873     uint8_t auBufB[_32K];
    1874 
    1875     int rc = VINF_SUCCESS;
    1876 
     1913 * Structure for keeping file comparison parameters for one file.
     1914 */
     1915typedef struct AUDIOTESTFILECMPPARMS
     1916{
     1917    /** File handle to file to compare. */
     1918    RTFILE   hFile;
     1919    /** Absolute offset (in bytes) to start comparing.
     1920     *  Ignored when set to 0. */
     1921    uint64_t offStart;
     1922    /** Size (in bytes) of area to compare.
     1923     *  Starts at \a offStart. */
     1924    uint64_t cbSize;
     1925} AUDIOTESTFILECMPPARMS;
     1926/** Pointer to file comparison parameters for one file. */
     1927typedef AUDIOTESTFILECMPPARMS *PAUDIOTESTFILECMPPARMS;
     1928
     1929/**
     1930 * Finds differences in two audio test files by binary comparing chunks.
     1931 *
     1932 * @returns Number of differences. 0 means they are equal (but not necessarily identical).
     1933 * @param   pCmpA               File comparison parameters to file A to compare file B with.
     1934 * @param   pCmpB               File comparison parameters to file B to compare file A with.
     1935 * @param   pToneParms          Tone parameters to use for comparison.
     1936 */
     1937static uint32_t audioTestFilesFindDiffsBinary(PAUDIOTESTFILECMPPARMS pCmpA, PAUDIOTESTFILECMPPARMS pCmpB,
     1938                                              PAUDIOTESTTONEPARMS pToneParms)
     1939{
     1940    uint8_t auBufA[_4K];
     1941    uint8_t auBufB[_4K];
     1942
     1943    int rc = RTFileSeek(pCmpA->hFile, pCmpA->offStart, RTFILE_SEEK_BEGIN, NULL);
     1944    AssertRC(rc);
     1945
     1946    rc = RTFileSeek(pCmpB->hFile, pCmpB->offStart, RTFILE_SEEK_BEGIN, NULL);
     1947    AssertRC(rc);
     1948
     1949    RT_NOREF(pToneParms);
     1950    uint32_t const cbChunkSize = 4; //PDMAudioPropsMilliToBytes(&pToneParms->Props, 5 /* ms */);
     1951
     1952    uint64_t offCur      = 0;
     1953    uint64_t offLastDiff = 0;
     1954    uint32_t cDiffs      = 0;
     1955    uint64_t cbToCompare = RT_MIN(pCmpA->cbSize, pCmpB->cbSize);
    18771956    while (cbToCompare)
    18781957    {
    18791958        size_t cbReadA;
    1880         rc = RTFileRead(hFileA, auBufA, RT_MIN(cbToCompare, sizeof(auBufA)), &cbReadA);
     1959        rc = RTFileRead(pCmpA->hFile, auBufA, RT_MIN(cbToCompare, cbChunkSize), &cbReadA);
    18811960        AssertRCBreak(rc);
    18821961        size_t cbReadB;
    1883         rc = RTFileRead(hFileB, auBufB, RT_MIN(cbToCompare, sizeof(auBufB)), &cbReadB);
     1962        rc = RTFileRead(pCmpB->hFile, auBufB, RT_MIN(cbToCompare, cbChunkSize), &cbReadB);
    18841963        AssertRCBreak(rc);
    18851964        AssertBreakStmt(cbReadA == cbReadB, rc = VERR_INVALID_PARAMETER); /** @todo Find a better rc. */
     1965
    18861966        if (memcmp(auBufA, auBufB, RT_MIN(cbReadA, cbReadB)) != 0)
    1887             return false;
    1888         Assert(cbToCompare >= cbReadA);
     1967        {
     1968            if (offLastDiff == 0) /* No consequitive different chunk? Count as new then. */
     1969            {
     1970                cDiffs++;
     1971                offLastDiff = offCur;
     1972            }
     1973        }
     1974        else /* Reset and count next difference as new then. */
     1975        {
     1976            if (cDiffs)
     1977            {
     1978                Log2Func(("Chunk A [%RU64-%RU64] vs. chunk B [%RU64-%RU64] (%RU64 bytes)\n",
     1979                          pCmpA->offStart + offLastDiff, pCmpA->offStart + offCur,
     1980                          pCmpB->offStart + offLastDiff, pCmpB->offStart + offCur, offCur - offLastDiff));
     1981            }
     1982            offLastDiff = 0;
     1983        }
     1984
     1985        AssertBreakStmt(cbToCompare >= cbReadA, VERR_INTERNAL_ERROR);
    18891986        cbToCompare -= cbReadA;
    1890     }
    1891 
    1892     return RT_SUCCESS(rc) && (cbToCompare == 0);
     1987        offCur      += cbReadA;
     1988    }
     1989
     1990    return cDiffs;
    18931991}
    18941992
     
    19912089    }
    19922090
    1993     if (!audioTestFilesCompareBinary(pObjA->File.hFile, pObjB->File.hFile, cbSizeA))
    1994     {
    1995         /** @todo Add more sophisticated stuff here. */
    1996 
    1997         int rc2 = audioTestErrorDescAddInfo(pVerJob->pErr, pVerJob->idxTest, "Files '%s' and '%s' have different content",
    1998                                             pObjA->szName, pObjB->szName);
     2091    /** @todo For now we only support comparison of data which do have identical PCM properties! */
     2092
     2093    AUDIOTESTTONEPARMS ToneParmsA;
     2094    RT_ZERO(ToneParmsA);
     2095    ToneParmsA.Props = pVerJob->PCMProps;
     2096
     2097    AUDIOTESTFILECMPPARMS FileA;
     2098    RT_ZERO(FileA);
     2099    FileA.hFile     = pObjA->File.hFile;
     2100    FileA.offStart  = audioTestToneFileFind(pObjA->File.hFile, true /* fFindSilence */, 0 /* uOff */, &ToneParmsA);
     2101    FileA.cbSize    = RT_MIN(audioTestToneFileFind(pObjA->File.hFile, false /* fFindSilence */, FileA.offStart,  &ToneParmsA) + 1,
     2102                             cbSizeA);
     2103
     2104    AUDIOTESTTONEPARMS ToneParmsB;
     2105    RT_ZERO(ToneParmsB);
     2106    ToneParmsB.Props = pVerJob->PCMProps;
     2107
     2108    AUDIOTESTFILECMPPARMS FileB;
     2109    RT_ZERO(FileB);
     2110    FileB.hFile     = pObjB->File.hFile;
     2111    FileB.offStart  = audioTestToneFileFind(pObjB->File.hFile, true /* fFindSilence */, 0 /* uOff */, &ToneParmsB);
     2112    FileB.cbSize    = RT_MIN(audioTestToneFileFind(pObjB->File.hFile, false /* fFindSilence */, FileB.offStart,  &ToneParmsB),
     2113                             cbSizeB);
     2114
     2115    Log2Func(("Test #%RU32\n", pVerJob->idxTest));
     2116    Log2Func(("File A ('%s'): cbOff=%RU64  cbSize=%RU64, cbFileSize=%RU64\n", pObjA->szName, FileA.offStart, FileA.cbSize - FileA.offStart, cbSizeA));
     2117    Log2Func(("File B ('%s'): cbOff=%RU64, cbSize=%RU64, cbFileSize=%RU64\n", pObjB->szName, FileB.offStart, FileB.cbSize - FileB.offStart, cbSizeB));
     2118
     2119    uint32_t const cDiffs = audioTestFilesFindDiffsBinary(&FileA, &FileB, &ToneParmsA);
     2120
     2121    int rc2 = audioTestErrorDescAddInfo(pVerJob->pErr, pVerJob->idxTest, "Files '%s' and '%s' are %s (%RU32 different chunks, threshold is %RU32)",
     2122                                        pObjA->szName, pObjB->szName, cDiffs == 0 ? "equal" : "different", cDiffs, pVerJob->cThresholdDiff);
     2123    AssertRC(rc2);
     2124
     2125    if (cDiffs > pVerJob->cThresholdDiff)
     2126    {
     2127        rc2 = audioTestErrorDescAddError(pVerJob->pErr, pVerJob->idxTest, "Files '%s' and '%s' do not match",
     2128                                         pObjA->szName, pObjB->szName);
    19992129        AssertRC(rc2);
    20002130    }
     
    20902220    VerJob.pSetB      = pSetB;
    20912221    VerJob.fKeepGoing = true; /** @todo Make this configurable. */
     2222
     2223    /** @todo For now we're very strict and consider any diff as being erroneous.
     2224     *        We might want / need to change this depending on the test boxes lateron. */
     2225    VerJob.cThresholdDiff = 0;
    20922226
    20932227    PAUDIOTESTVERIFYJOB pVerJob = &VerJob;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette