VirtualBox

Changeset 89466 in vbox for trunk/src/VBox/ValidationKit


Ignore:
Timestamp:
Jun 2, 2021 1:03:44 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144821
Message:

ValKit/AudioTest: Added a 'rec' command. bugref:10008

Location:
trunk/src/VBox/ValidationKit/utils/audio
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp

    r89460 r89466  
    5353# include <iprt/win/windows.h> /* for CoInitializeEx */
    5454#endif
     55#include <signal.h>
    5556
    5657/**
     
    391392AssertCompile(sizeof(g_aBackends) > 0 /* port me */);
    392393
    393 static volatile bool g_fTerminated = false;
     394
     395/** Terminate ASAP if set.  Set on Ctrl-C. */
     396static bool volatile    g_fTerminate = false;
    394397/** The release logger. */
    395 static PRTLOGGER    g_pRelLogger = NULL;
     398static PRTLOGGER        g_pRelLogger = NULL;
    396399
    397400
     
    404407/** DrvAudio: The debug output path. */
    405408const char   *g_pszDrvAudioDebug = NULL;
    406 
    407409
    408410
     
    12921294        RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "ATS running\n");
    12931295
    1294         while (!g_fTerminated) /** @todo Implement signal handling. */
     1296        while (!g_fTerminate) /** @todo Implement signal handling. */
    12951297        {
    12961298            RTThreadSleep(100);
     
    18211823    uint32_t const  cbSamplesAligned = PDMAudioPropsFloorBytesToFrame(pMix->pProps, sizeof(abSamples));
    18221824    uint64_t        offStream        = 0;
    1823     for (;;)
     1825    while (!g_fTerminate)
    18241826    {
    18251827        /* Read a chunk from the wave file. */
     
    18541856                        }
    18551857                        else
    1856                             return RTMsgErrorExitFailure("Played zero out of %#x bytes - %#x bytes reported playable!\n",
    1857                                                          cbToPlay, cbCanWrite);
     1858                            return RTMsgErrorExitFailure("Played zero bytes - %#x bytes reported playable!\n", cbCanWrite);
    18581859                    }
    18591860                    else
     
    19591960                {
    19601961                    if (g_uVerbosity > 0)
    1961                         RTMsgInfo("Stream: %s cbBacked=%#RX32%s\n", PDMAudioPropsToString(&pStream->Props, szTmp, sizeof(szTmp)),
     1962                        RTMsgInfo("Stream: %s cbBackend=%#RX32%s\n", PDMAudioPropsToString(&pStream->Props, szTmp, sizeof(szTmp)),
    19621963                                  pStream->cbBackend, fWithMixer ? " mixed" : "");
    19631964
     
    19651966                     * Enable the stream and start playing.
    19661967                     */
    1967                     rc = audioTestDriverStackStreamEnable(&DrvStack, pStream);
     1968                    rc = AudioTestMixStreamEnable(&Mix);
    19681969                    if (RT_SUCCESS(rc))
    19691970                        rcExit = audioTestPlayOneInner(&Mix, &WaveFile, &CfgAcq, pszFile);
     
    20992100
    21002101/*********************************************************************************************************************************
     2102*   Command: rec                                                                                                                 *
     2103*********************************************************************************************************************************/
     2104
     2105/**
     2106 * Worker for audioTestRecOne implementing the recording loop.
     2107 */
     2108static RTEXITCODE audioTestRecOneInner(PAUDIOTESTDRVMIXSTREAM pMix, PAUDIOTESTWAVEFILE pWaveFile,
     2109                                       PCPDMAUDIOSTREAMCFG pCfgAcq, uint64_t cMaxFrames, const char *pszFile)
     2110{
     2111    int             rc;
     2112    uint32_t const  cbPreBuffer = PDMAudioPropsFramesToBytes(pMix->pProps, pCfgAcq->Backend.cFramesPreBuffering);
     2113    uint64_t const  nsStarted   = RTTimeNanoTS();
     2114
     2115    /*
     2116     * Transfer data as quickly as we're allowed.
     2117     */
     2118    uint8_t         abSamples[16384];
     2119    uint32_t const  cbSamplesAligned     = PDMAudioPropsFloorBytesToFrame(pMix->pProps, sizeof(abSamples));
     2120    uint64_t        cFramesCapturedTotal = 0;
     2121    while (!g_fTerminate && cFramesCapturedTotal < cMaxFrames)
     2122    {
     2123        /*
     2124         * Anything we can read?
     2125         */
     2126        uint32_t const cbCanRead = AudioTestMixStreamGetReadable(pMix);
     2127        if (cbCanRead)
     2128        {
     2129            uint32_t const cbToRead   = RT_MIN(cbCanRead, cbSamplesAligned);
     2130            uint32_t       cbCaptured = 0;
     2131            rc = AudioTestMixStreamCapture(pMix, abSamples, cbToRead, &cbCaptured);
     2132            if (RT_SUCCESS(rc))
     2133            {
     2134                if (cbCaptured)
     2135                {
     2136                    uint32_t cFramesCaptured = PDMAudioPropsBytesToFrames(pMix->pProps, cbCaptured);
     2137                    if (cFramesCaptured + cFramesCaptured < cMaxFrames)
     2138                    { /* likely */ }
     2139                    else
     2140                    {
     2141                        cFramesCaptured = cMaxFrames - cFramesCaptured;
     2142                        cbCaptured      = PDMAudioPropsFramesToBytes(pMix->pProps, cFramesCaptured);
     2143                    }
     2144
     2145                    rc = AudioTestWaveFileWrite(pWaveFile, abSamples, cbCaptured);
     2146                    if (RT_SUCCESS(rc))
     2147                        cFramesCapturedTotal += cFramesCaptured;
     2148                    else
     2149                        return RTMsgErrorExitFailure("Error writing to '%s': %Rrc", pszFile, rc);
     2150                }
     2151                else
     2152                    return RTMsgErrorExitFailure("Captured zero bytes - %#x bytes reported readable!\n", cbCanRead);
     2153            }
     2154            else
     2155                return RTMsgErrorExitFailure("Failed to capture %#x bytes: %Rrc (%#x available)\n", cbToRead, rc, cbCanRead);
     2156        }
     2157        else if (AudioTestMixStreamIsOkay(pMix))
     2158            RTThreadSleep(RT_MIN(RT_MAX(1, pCfgAcq->Device.cMsSchedulingHint), 256));
     2159        else
     2160            return RTMsgErrorExitFailure("Stream is not okay!\n");
     2161    }
     2162
     2163    /*
     2164     * Disable the stream.
     2165     */
     2166    rc = AudioTestMixStreamDisable(pMix);
     2167    if (RT_SUCCESS(rc) && g_uVerbosity > 0)
     2168        RTMsgInfo("%'RU64 ns: Stopped after recording %RU64 frames%s\n", RTTimeNanoTS() - nsStarted, cFramesCapturedTotal,
     2169                  g_fTerminate ? " - Ctrl-C" : ".");
     2170    else if (RT_FAILURE(rc))
     2171        return RTMsgErrorExitFailure("Disabling stream failed: %Rrc", rc);
     2172
     2173    return RTEXITCODE_SUCCESS;
     2174}
     2175
     2176
     2177/**
     2178 * Worker for audioTestCmdRecHandler that recs one file.
     2179 */
     2180static RTEXITCODE audioTestRecOne(const char *pszFile, uint8_t cWaveChannels, uint8_t cbWaveSample, uint32_t uWaveHz,
     2181                                  PCPDMDRVREG pDrvReg, const char *pszDevId, uint32_t cMsBufferSize,
     2182                                  uint32_t cMsPreBuffer, uint32_t cMsSchedulingHint,
     2183                                  uint8_t cChannels, uint8_t cbSample, uint32_t uHz, bool fWithDrvAudio, bool fWithMixer,
     2184                                  uint64_t cMaxFrames, uint64_t cNsMaxDuration)
     2185{
     2186    /*
     2187     * Construct the driver stack.
     2188     */
     2189    RTEXITCODE          rcExit = RTEXITCODE_FAILURE;
     2190    AUDIOTESTDRVSTACK   DrvStack;
     2191    int rc = audioTestDriverStackInit(&DrvStack, pDrvReg, fWithDrvAudio);
     2192    if (RT_SUCCESS(rc))
     2193    {
     2194        /*
     2195         * Set the input device if one is specified.
     2196         */
     2197        rc = audioTestDriverStackSetDevice(&DrvStack, PDMAUDIODIR_IN, pszDevId);
     2198        if (RT_SUCCESS(rc))
     2199        {
     2200            /*
     2201             * Create an input stream.
     2202             */
     2203            PDMAUDIOPCMPROPS  ReqProps;
     2204            PDMAudioPropsInit(&ReqProps,
     2205                              cbSample ? cbSample : cbWaveSample ? cbWaveSample : 2,
     2206                              true /*fSigned*/,
     2207                              cChannels ? cChannels : cWaveChannels ? cWaveChannels : 2,
     2208                              uHz ? uHz : uWaveHz ? uWaveHz : 44100);
     2209            PDMAUDIOSTREAMCFG CfgAcq;
     2210            PPDMAUDIOSTREAM   pStream  = NULL;
     2211            rc = audioTestDriverStackStreamCreateInput(&DrvStack, &ReqProps, cMsBufferSize,
     2212                                                       cMsPreBuffer, cMsSchedulingHint, &pStream, &CfgAcq);
     2213            if (RT_SUCCESS(rc))
     2214            {
     2215                /*
     2216                 * Determine the wave file properties.  If it differs from the stream
     2217                 * properties, make sure the mixer is enabled.
     2218                 */
     2219                PDMAUDIOPCMPROPS WaveProps;
     2220                PDMAudioPropsInit(&WaveProps,
     2221                                  cbWaveSample ? cbWaveSample : PDMAudioPropsSampleSize(&CfgAcq.Props),
     2222                                  true /*fSigned*/,
     2223                                  cWaveChannels ? cWaveChannels : PDMAudioPropsChannels(&CfgAcq.Props),
     2224                                  uWaveHz ? uWaveHz : PDMAudioPropsHz(&CfgAcq.Props));
     2225                if (!fWithMixer && !PDMAudioPropsAreEqual(&WaveProps, &CfgAcq.Props))
     2226                {
     2227                    RTMsgInfo("Enabling the mixer buffer.\n");
     2228                    fWithMixer = true;
     2229                }
     2230
     2231                /* Console the max duration into frames now that we've got the wave file format. */
     2232                if (cMaxFrames != UINT64_MAX && cNsMaxDuration != UINT64_MAX)
     2233                {
     2234                    uint64_t cMaxFrames2 = PDMAudioPropsNanoToBytes64(&WaveProps, cNsMaxDuration);
     2235                    cMaxFrames = RT_MAX(cMaxFrames, cMaxFrames2);
     2236                }
     2237                else if (cNsMaxDuration != UINT64_MAX)
     2238                    cMaxFrames = PDMAudioPropsNanoToBytes64(&WaveProps, cNsMaxDuration);
     2239
     2240                /*
     2241                 * Create a mixer wrapper.  This is just a thin wrapper if fWithMixer
     2242                 * is false, otherwise it's doing mixing, resampling and recoding.
     2243                 */
     2244                AUDIOTESTDRVMIXSTREAM Mix;
     2245                rc = AudioTestMixStreamInit(&Mix, &DrvStack, pStream, fWithMixer ? &WaveProps : NULL, 100 /*ms*/);
     2246                if (RT_SUCCESS(rc))
     2247                {
     2248                    char szTmp[128];
     2249                    if (g_uVerbosity > 0)
     2250                        RTMsgInfo("Stream: %s cbBackend=%#RX32%s\n", PDMAudioPropsToString(&pStream->Props, szTmp, sizeof(szTmp)),
     2251                                  pStream->cbBackend, fWithMixer ? " mixed" : "");
     2252
     2253                    /*
     2254                     * Open the wave output file.
     2255                     */
     2256                    AUDIOTESTWAVEFILE WaveFile;
     2257                    RTERRINFOSTATIC ErrInfo;
     2258                    rc = AudioTestWaveFileCreate(pszFile, &WaveProps, &WaveFile, RTErrInfoInitStatic(&ErrInfo));
     2259                    if (RT_SUCCESS(rc))
     2260                    {
     2261                        if (g_uVerbosity > 0)
     2262                        {
     2263                            RTMsgInfo("Opened '%s' for playing\n", pszFile);
     2264                            RTMsgInfo("Format: %s\n", PDMAudioPropsToString(&WaveFile.Props, szTmp, sizeof(szTmp)));
     2265                        }
     2266
     2267                        /*
     2268                         * Enable the stream and start recording.
     2269                         */
     2270                        rc = AudioTestMixStreamEnable(&Mix);
     2271                        if (RT_SUCCESS(rc))
     2272                            rcExit = audioTestRecOneInner(&Mix, &WaveFile, &CfgAcq, cMaxFrames, pszFile);
     2273                        else
     2274                            rcExit = RTMsgErrorExitFailure("Enabling the input stream failed: %Rrc", rc);
     2275                        if (rcExit != RTEXITCODE_SUCCESS)
     2276                            AudioTestMixStreamDisable(&Mix);
     2277
     2278                        /*
     2279                         * Clean up.
     2280                         */
     2281                        rc = AudioTestWaveFileClose(&WaveFile);
     2282                        if (RT_FAILURE(rc))
     2283                            rcExit = RTMsgErrorExitFailure("Error closing '%s': %Rrc", pszFile, rc);
     2284                    }
     2285                    else
     2286                        rcExit = RTMsgErrorExitFailure("Failed to open '%s': %Rrc%#RTeim", pszFile, rc, &ErrInfo.Core.pszMsg);
     2287
     2288                    AudioTestMixStreamTerm(&Mix);
     2289                }
     2290                audioTestDriverStackStreamDestroy(&DrvStack, pStream);
     2291            }
     2292            else
     2293                rcExit = RTMsgErrorExitFailure("Creating output stream failed: %Rrc", rc);
     2294        }
     2295        else
     2296            rcExit = RTMsgErrorExitFailure("Failed to set output device to '%s': %Rrc", pszDevId, rc);
     2297        audioTestDriverStackDelete(&DrvStack);
     2298    }
     2299    else
     2300        rcExit = RTMsgErrorExitFailure("Driver stack construction failed: %Rrc", rc);
     2301    return rcExit;
     2302}
     2303
     2304/**
     2305 * Options for 'rec'.
     2306 */
     2307static const RTGETOPTDEF g_aCmdRecOptions[] =
     2308{
     2309    { "--backend",          'b',                          RTGETOPT_REQ_STRING  },
     2310    { "--channels",         'c',                          RTGETOPT_REQ_UINT8 },
     2311    { "--hz",               'f',                          RTGETOPT_REQ_UINT32 },
     2312    { "--frequency",        'f',                          RTGETOPT_REQ_UINT32 },
     2313    { "--sample-size",      'z',                          RTGETOPT_REQ_UINT8 },
     2314    { "--input-device",     'i',                          RTGETOPT_REQ_STRING  },
     2315    { "--wav-channels",     'C',                          RTGETOPT_REQ_UINT8 },
     2316    { "--wav-hz",           'F',                          RTGETOPT_REQ_UINT32 },
     2317    { "--wav-frequency",    'F',                          RTGETOPT_REQ_UINT32 },
     2318    { "--wav-sample-size",  'Z',                          RTGETOPT_REQ_UINT8 },
     2319    { "--with-drv-audio",   'd',                          RTGETOPT_REQ_NOTHING },
     2320    { "--with-mixer",       'm',                          RTGETOPT_REQ_NOTHING },
     2321    { "--max-frames",       'r',                          RTGETOPT_REQ_UINT64 },
     2322    { "--max-sec",          's',                          RTGETOPT_REQ_UINT64 },
     2323    { "--max-seconds",      's',                          RTGETOPT_REQ_UINT64 },
     2324    { "--max-ms",           't',                          RTGETOPT_REQ_UINT64 },
     2325    { "--max-milliseconds", 't',                          RTGETOPT_REQ_UINT64 },
     2326    { "--max-ns",           'T',                          RTGETOPT_REQ_UINT64 },
     2327    { "--max-nanoseconds",  'T',                          RTGETOPT_REQ_UINT64 },
     2328};
     2329
     2330/** The 'rec' command option help. */
     2331static DECLCALLBACK(const char *) audioTestCmdRecHelp(PCRTGETOPTDEF pOpt)
     2332{
     2333    switch (pOpt->iShort)
     2334    {
     2335        case 'b': return "The audio backend to use.";
     2336        case 'c': return "Number of backend input channels";
     2337        case 'C': return "Number of wave-file channels";
     2338        case 'd': return "Go via DrvAudio instead of directly interfacing with the backend.";
     2339        case 'f': return "Input frequency (Hz)";
     2340        case 'F': return "Wave-file frequency (Hz)";
     2341        case 'z': return "Input sample size (bits)";
     2342        case 'Z': return "Wave-file sample size (bits)";
     2343        case 'm': return "Go via the mixer.";
     2344        case 'i': return "The ID of the input device to use.";
     2345        case 'r': return "Max recording duration in frames.";
     2346        case 's': return "Max recording duration in seconds.";
     2347        case 't': return "Max recording duration in milliseconds.";
     2348        case 'T': return "Max recording duration in nanoseconds.";
     2349        default:  return NULL;
     2350    }
     2351}
     2352
     2353/**
     2354 * The 'play' command handler.
     2355 *
     2356 * @returns Program exit code.
     2357 * @param   pGetState   RTGetOpt state.
     2358 */
     2359static DECLCALLBACK(RTEXITCODE) audioTestCmdRecHandler(PRTGETOPTSTATE pGetState)
     2360{
     2361    /* Option values: */
     2362    PCPDMDRVREG pDrvReg             = g_aBackends[0].pDrvReg;
     2363    uint32_t    cMsBufferSize       = UINT32_MAX;
     2364    uint32_t    cMsPreBuffer        = UINT32_MAX;
     2365    uint32_t    cMsSchedulingHint   = UINT32_MAX;
     2366    const char *pszDevId            = NULL;
     2367    bool        fWithDrvAudio       = false;
     2368    bool        fWithMixer          = false;
     2369    uint8_t     cbSample            = 0;
     2370    uint8_t     cChannels           = 0;
     2371    uint32_t    uHz                 = 0;
     2372    uint8_t     cbWaveSample        = 0;
     2373    uint8_t     cWaveChannels       = 0;
     2374    uint32_t    uWaveHz             = 0;
     2375    uint64_t    cMaxFrames          = UINT64_MAX;
     2376    uint64_t    cNsMaxDuration      = UINT64_MAX;
     2377
     2378    /* Argument processing loop: */
     2379    int           rc;
     2380    RTGETOPTUNION ValueUnion;
     2381    while ((rc = RTGetOpt(pGetState, &ValueUnion)) != 0)
     2382    {
     2383        switch (rc)
     2384        {
     2385            case 'b':
     2386                pDrvReg = audioTestFindBackendOpt(ValueUnion.psz);
     2387                if (pDrvReg == NULL)
     2388                    return RTEXITCODE_SYNTAX;
     2389                break;
     2390
     2391            case 'c':
     2392                cChannels = ValueUnion.u8;
     2393                break;
     2394
     2395            case 'C':
     2396                cWaveChannels = ValueUnion.u8;
     2397                break;
     2398
     2399            case 'd':
     2400                fWithDrvAudio = true;
     2401                break;
     2402
     2403            case 'f':
     2404                uHz = ValueUnion.u32;
     2405                break;
     2406
     2407            case 'F':
     2408                uWaveHz = ValueUnion.u32;
     2409                break;
     2410
     2411            case 'i':
     2412                pszDevId = ValueUnion.psz;
     2413                break;
     2414
     2415            case 'm':
     2416                fWithMixer = true;
     2417                break;
     2418
     2419            case 'r':
     2420                cMaxFrames = ValueUnion.u64;
     2421                break;
     2422
     2423            case 's':
     2424                cNsMaxDuration = ValueUnion.u64 >= UINT64_MAX / RT_NS_1SEC ? UINT64_MAX : ValueUnion.u64 * RT_NS_1SEC;
     2425                break;
     2426
     2427            case 't':
     2428                cNsMaxDuration = ValueUnion.u64 >= UINT64_MAX / RT_NS_1MS  ? UINT64_MAX : ValueUnion.u64 * RT_NS_1MS;
     2429                break;
     2430
     2431            case 'T':
     2432                cNsMaxDuration = ValueUnion.u64;
     2433                break;
     2434
     2435            case 'z':
     2436                cbSample = ValueUnion.u8 / 8;
     2437                break;
     2438
     2439            case 'Z':
     2440                cbWaveSample = ValueUnion.u8 / 8;
     2441                break;
     2442
     2443            case VINF_GETOPT_NOT_OPTION:
     2444            {
     2445                RTEXITCODE rcExit = audioTestRecOne(ValueUnion.psz, cWaveChannels, cbWaveSample, uWaveHz,
     2446                                                    pDrvReg, pszDevId, cMsBufferSize, cMsPreBuffer, cMsSchedulingHint,
     2447                                                    cChannels, cbSample, uHz, fWithDrvAudio, fWithMixer,
     2448                                                    cMaxFrames, cNsMaxDuration);
     2449                if (rcExit != RTEXITCODE_SUCCESS)
     2450                    return rcExit;
     2451                break;
     2452            }
     2453
     2454            AUDIO_TEST_COMMON_OPTION_CASES(ValueUnion);
     2455
     2456            default:
     2457                return RTGetOptPrintError(rc, &ValueUnion);
     2458        }
     2459    }
     2460    return RTEXITCODE_SUCCESS;
     2461}
     2462
     2463
     2464/*********************************************************************************************************************************
    21012465*   Command: selftest                                                                                                            *
    21022466*********************************************************************************************************************************/
     
    22862650
    22872651/**
     2652 * Ctrl-C signal handler.
     2653 *
     2654 * This just sets g_fTerminate and hope it will be noticed soon.  It restores
     2655 * the SIGINT action to default, so that a second Ctrl-C will have the normal
     2656 * effect (just in case the code doesn't respond to g_fTerminate).
     2657 */
     2658static void audioTestSignalHandler(int iSig) RT_NOEXCEPT
     2659{
     2660    Assert(iSig == SIGINT); RT_NOREF(iSig);
     2661    RTPrintf("Ctrl-C!\n");
     2662    ASMAtomicWriteBool(&g_fTerminate, true);
     2663    signal(SIGINT, SIG_DFL);
     2664}
     2665
     2666
     2667/**
    22882668 * Commands.
    22892669 */
     
    23242704        "Plays one or more wave files.",
    23252705        g_aCmdPlayOptions,      RT_ELEMENTS(g_aCmdPlayOptions),     audioTestCmdPlayHelp,
     2706    },
     2707    {
     2708        "rec",      audioTestCmdRecHandler,
     2709        "Records audio to a wave file.",
     2710        g_aCmdRecOptions,       RT_ELEMENTS(g_aCmdRecOptions),      audioTestCmdRecHelp,
    23262711    },
    23272712    {
     
    24302815
    24312816    /*
     2817     * Install a Ctrl-C signal handler.
     2818     */
     2819#ifdef RT_OS_WINDOWS
     2820    signal(SIGINT, audioTestSignalHandler);
     2821#else
     2822    struct sigaction sa;
     2823    RT_ZERO(sa);
     2824    sa.sa_handler = audioTestSignalHandler;
     2825    sigaction(SIGINT, &sa, NULL);
     2826#endif
     2827
     2828    /*
    24322829     * Process common options.
    24332830     */
  • trunk/src/VBox/ValidationKit/utils/audio/vkatDriverStack.cpp

    r89444 r89466  
    623623                {
    624624                    pStreamAt->Core.uMagic     = PDMAUDIOSTREAM_MAGIC;
    625                     pStreamAt->Core.enmDir     = PDMAUDIODIR_OUT;
     625                    pStreamAt->Core.enmDir     = pCfgReq->enmDir;
    626626                    pStreamAt->Core.cbBackend  = cbStream;
    627627                    pStreamAt->Core.Props      = pCfgReq->Props;
     
    10441044    else
    10451045    {
    1046         PAUDIOTESTDRVSTACKSTREAM pStreamAt    = (PAUDIOTESTDRVSTACKSTREAM)pStream;
     1046        PAUDIOTESTDRVSTACKSTREAM pStreamAt = (PAUDIOTESTDRVSTACKSTREAM)pStream;
    10471047        cbWritable = pDrvStack->pIHostAudio->pfnStreamGetWritable(pDrvStack->pIHostAudio, &pStreamAt->Backend);
    10481048    }
     
    10621062        rc = pDrvStack->pIAudioConnector->pfnStreamPlay(pDrvStack->pIAudioConnector, pStream, pvBuf, cbBuf, pcbPlayed);
    10631063        if (RT_FAILURE(rc))
    1064             RTTestFailed(g_hTest, "pfnStreamPlay(,,,%#x) failed: %Rrc", cbBuf, rc);
     1064            RTTestFailed(g_hTest, "pfnStreamPlay(,,,%#x,) failed: %Rrc", cbBuf, rc);
    10651065    }
    10661066    else
     
    10691069        rc = pDrvStack->pIHostAudio->pfnStreamPlay(pDrvStack->pIHostAudio, &pStreamAt->Backend, pvBuf, cbBuf, pcbPlayed);
    10701070        if (RT_FAILURE(rc))
    1071             RTTestFailed(g_hTest, "PDMIHOSTAUDIO::pfnStreamPlay(,,,%#x) failed: %Rrc", cbBuf, rc);
     1071            RTTestFailed(g_hTest, "PDMIHOSTAUDIO::pfnStreamPlay(,,,%#x,) failed: %Rrc", cbBuf, rc);
    10721072    }
    10731073    return rc;
     1074}
     1075
     1076
     1077/**
     1078 * Gets the number of bytes it's currently possible to write to the stream.
     1079 */
     1080uint32_t audioTestDriverStackStreamGetReadable(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream)
     1081{
     1082    uint32_t cbReadable;
     1083    if (pDrvStack->pIAudioConnector)
     1084        cbReadable = pDrvStack->pIAudioConnector->pfnStreamGetReadable(pDrvStack->pIAudioConnector, pStream);
     1085    else
     1086    {
     1087        PAUDIOTESTDRVSTACKSTREAM pStreamAt = (PAUDIOTESTDRVSTACKSTREAM)pStream;
     1088        cbReadable = pDrvStack->pIHostAudio->pfnStreamGetReadable(pDrvStack->pIHostAudio, &pStreamAt->Backend);
     1089    }
     1090    return cbReadable;
    10741091}
    10751092
     
    10861103        rc = pDrvStack->pIAudioConnector->pfnStreamCapture(pDrvStack->pIAudioConnector, pStream, pvBuf, cbBuf, pcbCaptured);
    10871104        if (RT_FAILURE(rc))
    1088             RTTestFailed(g_hTest, "pfnStreamCapture(,,,%#x) failed: %Rrc", cbBuf, rc);
     1105            RTTestFailed(g_hTest, "pfnStreamCapture(,,,%#x,) failed: %Rrc", cbBuf, rc);
    10891106    }
    10901107    else
     
    10931110        rc = pDrvStack->pIHostAudio->pfnStreamCapture(pDrvStack->pIHostAudio, &pStreamAt->Backend, pvBuf, cbBuf, pcbCaptured);
    10941111        if (RT_FAILURE(rc))
    1095             RTTestFailed(g_hTest, "PDMIHOSTAUDIO::pfnStreamCapture(,,,%#x) failed: %Rrc", cbBuf, rc);
     1112            RTTestFailed(g_hTest, "PDMIHOSTAUDIO::pfnStreamCapture(,,,%#x,) failed: %Rrc", cbBuf, rc);
    10961113    }
    10971114    return rc;
     
    12491266
    12501267/**
     1268 * Same as audioTestDriverStackStreamEnable.
     1269 */
     1270int AudioTestMixStreamEnable(PAUDIOTESTDRVMIXSTREAM pMix)
     1271{
     1272    return audioTestDriverStackStreamEnable(pMix->pDrvStack, pMix->pStream);
     1273}
     1274
     1275
     1276/**
    12511277 * Same as audioTestDriverStackStreamDrain.
    12521278 */
     
    12721298}
    12731299
    1274 
    1275 /**
    1276  * Same as audioTestDriverStackStreamEnable.
    1277  */
    1278 int AudioTestMixStreamEnable(PAUDIOTESTDRVMIXSTREAM pMix)
    1279 {
    1280     return audioTestDriverStackStreamEnable(pMix->pDrvStack, pMix->pStream);
     1300/**
     1301 * Same as audioTestDriverStackStreamDisable.
     1302 */
     1303int AudioTestMixStreamDisable(PAUDIOTESTDRVMIXSTREAM pMix)
     1304{
     1305    return AudioTestDriverStackStreamDisable(pMix->pDrvStack, pMix->pStream);
     1306}
     1307
     1308
     1309/**
     1310 * Same as audioTestDriverStackStreamIsOkay.
     1311 */
     1312bool AudioTestMixStreamIsOkay(PAUDIOTESTDRVMIXSTREAM pMix)
     1313{
     1314    return audioTestDriverStackStreamIsOkay(pMix->pDrvStack, pMix->pStream);
    12811315}
    12821316
     
    12991333
    13001334
    1301 /**
    1302  * Same as audioTestDriverStackStreamIsOkay.
    1303  */
    1304 bool AudioTestMixStreamIsOkay(PAUDIOTESTDRVMIXSTREAM pMix)
    1305 {
    1306     return audioTestDriverStackStreamIsOkay(pMix->pDrvStack, pMix->pStream);
    1307 }
    13081335
    13091336
     
    13491376}
    13501377
     1378
     1379/**
     1380 * Same as audioTestDriverStackStreamGetReadable
     1381 */
     1382uint32_t AudioTestMixStreamGetReadable(PAUDIOTESTDRVMIXSTREAM pMix)
     1383{
     1384    if (!pMix->fDoMixing)
     1385        return audioTestDriverStackStreamGetReadable(pMix->pDrvStack, pMix->pStream);
     1386
     1387    audioTestMixStreamTransfer(pMix);
     1388    uint32_t cbRet = AudioMixBufUsedBytes(&pMix->MixBuf);
     1389    return cbRet;
     1390}
     1391
     1392
     1393
     1394
     1395/**
     1396 * Same as audioTestDriverStackStreamCapture.
     1397 */
     1398int AudioTestMixStreamCapture(PAUDIOTESTDRVMIXSTREAM pMix, void *pvBuf, uint32_t cbBuf, uint32_t *pcbCaptured)
     1399{
     1400    if (!pMix->fDoMixing)
     1401        return audioTestDriverStackStreamCapture(pMix->pDrvStack, pMix->pStream, pvBuf, cbBuf, pcbCaptured);
     1402
     1403    *pcbCaptured = 0;
     1404
     1405    int rc = audioTestMixStreamTransfer(pMix);
     1406    if (RT_FAILURE(rc))
     1407        return rc;
     1408
     1409    uint32_t const cbFrame = PDMAudioPropsFrameSize(&pMix->MixBuf.Props);
     1410    while (cbBuf >= cbFrame)
     1411    {
     1412        uint32_t const cFrames = AudioMixBufUsed(&pMix->MixBuf);
     1413        if (!cFrames)
     1414            break;
     1415        uint32_t cbToRead = PDMAudioPropsFramesToBytes(&pMix->MixBuf.Props, cFrames);
     1416        cbToRead = RT_MIN(cbToRead, cbBuf);
     1417        cbToRead = PDMAudioPropsFloorBytesToFrame(&pMix->MixBuf.Props, cbToRead);
     1418
     1419        uint32_t cFramesPeeked = 0;
     1420        uint32_t cbPeeked      = 0;
     1421        AudioMixBufPeek(&pMix->MixBuf, 0 /*offSrcFrame*/, cFrames, &cFramesPeeked, &pMix->PeekState, pvBuf, cbToRead, &cbPeeked);
     1422        Assert(cFramesPeeked == PDMAudioPropsBytesToFrames(&pMix->MixBuf.Props, cbPeeked));
     1423        AudioMixBufAdvance(&pMix->MixBuf, cFramesPeeked);
     1424
     1425        *pcbCaptured += cbToRead;
     1426        cbBuf        -= cbToRead;
     1427        pvBuf         = (uint8_t *)pvBuf + cbToRead;
     1428
     1429        rc = audioTestMixStreamTransfer(pMix);
     1430        if (RT_FAILURE(rc))
     1431            return *pcbCaptured ? VINF_SUCCESS : rc;
     1432    }
     1433
     1434    return VINF_SUCCESS;
     1435}
     1436
  • trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h

    r89439 r89466  
    130130int         audioTestDriverStackStreamDrain(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream, bool fSync);
    131131int         audioTestDriverStackStreamEnable(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream);
    132 int         audioTestDriverStackStreamDisable(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream);
     132int         AudioTestDriverStackStreamDisable(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream);
     133bool        audioTestDriverStackStreamIsOkay(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream);
    133134uint32_t    audioTestDriverStackStreamGetWritable(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream);
    134 bool        audioTestDriverStackStreamIsOkay(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream);
    135135int         audioTestDriverStackStreamPlay(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream, void const *pvBuf,
    136136                                           uint32_t cbBuf, uint32_t *pcbPlayed);
     137uint32_t    audioTestDriverStackStreamGetReadable(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream);
    137138int         audioTestDriverStackStreamCapture(PAUDIOTESTDRVSTACK pDrvStack, PPDMAUDIOSTREAM pStream,
    138139                                              void *pvBuf, uint32_t cbBuf, uint32_t *pcbCaptured);
     
    145146                                   PCPDMAUDIOPCMPROPS pProps, uint32_t cMsBuffer);
    146147void        AudioTestMixStreamTerm(PAUDIOTESTDRVMIXSTREAM pMix);
     148int         AudioTestMixStreamEnable(PAUDIOTESTDRVMIXSTREAM pMix);
    147149int         AudioTestMixStreamDrain(PAUDIOTESTDRVMIXSTREAM pMix, bool fSync);
    148 int         AudioTestMixStreamEnable(PAUDIOTESTDRVMIXSTREAM pMix);
     150int         AudioTestMixStreamDisable(PAUDIOTESTDRVMIXSTREAM pMix);
     151bool        AudioTestMixStreamIsOkay(PAUDIOTESTDRVMIXSTREAM pMix);
    149152uint32_t    AudioTestMixStreamGetWritable(PAUDIOTESTDRVMIXSTREAM pMix);
    150 bool        AudioTestMixStreamIsOkay(PAUDIOTESTDRVMIXSTREAM pMix);
    151153int         AudioTestMixStreamPlay(PAUDIOTESTDRVMIXSTREAM pMix, void const *pvBuf, uint32_t cbBuf, uint32_t *pcbPlayed);
     154uint32_t    AudioTestMixStreamGetReadable(PAUDIOTESTDRVMIXSTREAM pMix);
    152155int         AudioTestMixStreamCapture(PAUDIOTESTDRVMIXSTREAM pMix, void *pvBuf, uint32_t cbBuf, uint32_t *pcbCaptured);
    153156/** @}  */
Note: See TracChangeset for help on using the changeset viewer.

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