- Timestamp:
- Nov 3, 2021 5:27:10 PM (3 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioTest.cpp
r91912 r92195 156 156 * Must not contain a path and has to be able to serialize to disk. */ 157 157 char szName[256]; 158 /** The test type. */ 159 AUDIOTESTTYPE enmTestType; 158 160 /** The object type. */ 159 161 AUDIOTESTOBJTYPE enmType; … … 2322 2324 2323 2325 /** 2326 * Initializes a audio test audio beacon. 2327 * 2328 * @returns VBox status code. 2329 * @param pBeacon Audio test beacon to (re-)initialize. 2330 * @param enmType Beacon type to set. 2331 * @param pProps PCM properties to use for producing audio beacon data. 2332 */ 2333 void AudioTestBeaconInit(PAUDIOTESTTONEBEACON pBeacon, AUDIOTESTTONEBEACONTYPE enmType, PPDMAUDIOPCMPROPS pProps) 2334 { 2335 AssertReturnVoid(PDMAudioPropsFrameSize(pProps) == 4); /** @todo Make this more dynamic. */ 2336 2337 RT_BZERO(pBeacon, sizeof(AUDIOTESTTONEBEACON)); 2338 2339 pBeacon->enmType = enmType; 2340 memcpy(&pBeacon->Props, pProps, sizeof(PDMAUDIOPCMPROPS)); 2341 2342 pBeacon->cbToProcess = PDMAudioPropsFramesToBytes(&pBeacon->Props, AUDIOTEST_BEACON_SIZE_FRAMES); 2343 } 2344 2345 /** 2346 * Returns the beacon byte of a beacon type. 2347 * 2348 * @returns Beacon byte if found, 0 otherwise. 2349 * @param enmType Beacon type to get beacon byte for. 2350 */ 2351 DECLINLINE(uint8_t) AudioTestBeaconByteFromType(AUDIOTESTTONEBEACONTYPE enmType) 2352 { 2353 switch (enmType) 2354 { 2355 case AUDIOTESTTONEBEACONTYPE_PLAY_PRE: return AUDIOTEST_BEACON_BYTE_PLAY_PRE; 2356 case AUDIOTESTTONEBEACONTYPE_PLAY_POST: return AUDIOTEST_BEACON_BYTE_PLAY_POST; 2357 case AUDIOTESTTONEBEACONTYPE_REC_PRE: return AUDIOTEST_BEACON_BYTE_REC_PRE; 2358 case AUDIOTESTTONEBEACONTYPE_REC_POST: return AUDIOTEST_BEACON_BYTE_REC_POST; 2359 default: break; 2360 } 2361 2362 AssertFailedReturn(0); 2363 return 0; /* Never reached. */ 2364 } 2365 2366 /** 2367 * Returns the total expected (total) size of an audio beacon (in bytes). 2368 * 2369 * @returns Beacon size in bytes. 2370 * @param pBeacon Beacon to get beacon size for. 2371 */ 2372 uint32_t AudioTestBeaconGetSize(PCAUDIOTESTTONEBEACON pBeacon) 2373 { 2374 return pBeacon->cbToProcess; 2375 } 2376 2377 /** 2378 * Returns the beacon type of an audio beacon. 2379 * 2380 * @returns Beacon type. 2381 * @param pBeacon Beacon to get beacon size for. 2382 */ 2383 AUDIOTESTTONEBEACONTYPE AudioTestBeaconGetType(PCAUDIOTESTTONEBEACON pBeacon) 2384 { 2385 return pBeacon->enmType; 2386 } 2387 2388 /** 2389 * Returns the remaining bytes (to be complete) of an audio beacon. 2390 * 2391 * @returns Remaining bytes. 2392 * @param pBeacon Beacon to get remaining size for. 2393 */ 2394 uint32_t AudioTestBeaconGetRemaining(PCAUDIOTESTTONEBEACON pBeacon) 2395 { 2396 return pBeacon->cbToProcess - pBeacon->cbProcessed; 2397 } 2398 2399 /** 2400 * Returns the already used (received) bytes (to be complete) of an audio beacon. 2401 * 2402 * @returns Used bytes. 2403 * @param pBeacon Beacon to get remaining size for. 2404 */ 2405 uint32_t AudioTestBeaconGetUsed(PCAUDIOTESTTONEBEACON pBeacon) 2406 { 2407 return pBeacon->cbProcessed; 2408 } 2409 2410 /** 2411 * Writes audio beacon data to a given buffer. 2412 * 2413 * @returns VBox status code. 2414 * @param pBeacon Beacon to write to buffer. 2415 * @param pvBuf Buffer to write to. 2416 * @param cbBuf Size (in bytes) of buffer to write to. 2417 */ 2418 int AudioTestBeaconWrite(PAUDIOTESTTONEBEACON pBeacon, void *pvBuf, uint32_t cbBuf) 2419 { 2420 AssertReturn(pBeacon->cbProcessed + cbBuf <= pBeacon->cbToProcess, VERR_BUFFER_OVERFLOW); 2421 2422 memset(pvBuf, AudioTestBeaconByteFromType(pBeacon->enmType), cbBuf); 2423 2424 pBeacon->cbProcessed += cbBuf; 2425 2426 return VINF_SUCCESS; 2427 } 2428 2429 /** 2430 * Converts an audio beacon type to a string. 2431 * 2432 * @returns Pointer to read-only audio beacon type string on success, 2433 * "illegal" if invalid command value. 2434 * @param enmType The type to convert. 2435 */ 2436 const char *AudioTestBeaconTypeGetName(AUDIOTESTTONEBEACONTYPE enmType) 2437 { 2438 switch (enmType) 2439 { 2440 case AUDIOTESTTONEBEACONTYPE_PLAY_PRE: return "pre-playback"; 2441 case AUDIOTESTTONEBEACONTYPE_PLAY_POST: return "post-playback"; 2442 case AUDIOTESTTONEBEACONTYPE_REC_PRE: return "pre-recording"; 2443 case AUDIOTESTTONEBEACONTYPE_REC_POST: return "post-recording"; 2444 default: break; 2445 } 2446 AssertMsgFailedReturn(("Invalid beacon type: #%x\n", enmType), "illegal"); 2447 } 2448 2449 uint32_t AudioTestBeaconAddConsecutive(PAUDIOTESTTONEBEACON pBeacon, const uint8_t *pauBuf, size_t cbBuf) 2450 { 2451 uint32_t const cbFrameSize = PDMAudioPropsFrameSize(&pBeacon->Props); /* Use the audio frame size as chunk size. */ 2452 2453 if (cbBuf < cbFrameSize) 2454 return 0; 2455 2456 AssertMsgReturn(cbBuf % cbFrameSize == 0, 2457 ("Buffer size must be frame-aligned"), VERR_INVALID_PARAMETER); 2458 2459 uint8_t const byBeacon = AudioTestBeaconByteFromType(pBeacon->enmType); 2460 /*bool fInBeacon = false; 2461 uint32_t cbBeacon = 0; 2462 size_t offLastBeacon = 0;*/ 2463 size_t offGap = 0; 2464 2465 unsigned const cbStep = cbFrameSize; 2466 uint32_t const cbProcessedInitial = pBeacon->cbProcessed; 2467 2468 for (size_t i = 0; i < cbBuf; i += cbStep) 2469 { 2470 if ( pauBuf[i] == byBeacon 2471 && pauBuf[i + 1] == byBeacon 2472 && pauBuf[i + 2] == byBeacon 2473 && pauBuf[i + 3] == byBeacon) 2474 { 2475 //if (pBeacon->cbProcessed) 2476 //{ 2477 //LogRel(("AudioTestBeaconAddConsecutive: Beacon %s started (last was %RU32@%zu)\n", AudioTestBeaconTypeGetName(pBeacon->enmType), cbBeacon, i)); 2478 if (offGap) 2479 { 2480 pBeacon->cbProcessed = 0; 2481 } 2482 pBeacon->cbProcessed += cbStep; 2483 offGap = 0; 2484 //fInBeacon = true; 2485 //offLastBeacon = i; 2486 //} 2487 //cbBeacon += cbFrameSize; 2488 } 2489 else 2490 { 2491 #if 0 2492 if (fInBeacon) 2493 { 2494 //LogRel(("AudioTestBeaconAddConsecutive: Beacon %s ended (%RU32@%zu)\n", AudioTestBeaconTypeGetName(pBeacon->enmType), cbBeacon, offLastBeacon)); 2495 fInBeacon = false; 2496 continue; 2497 } 2498 #endif 2499 offGap = i; 2500 } 2501 } 2502 2503 #if 0 2504 if ( cbBeacon 2505 && ( fInBeacon 2506 || offLastBeacon == 0) 2507 ) 2508 { 2509 pBeacon->cbProcessed += cbBeacon; 2510 Assert(pBeacon->cbProcessed <= pBeacon->cbToProcess); 2511 } 2512 2513 if (cbBeacon) 2514 LogRel(("AudioTestBeaconAddConsecutive: %s in=%RTbool cb=%RU32 -> cbProc=%RU32\n", AudioTestBeaconTypeGetName(pBeacon->enmType), fInBeacon, cbBeacon, pBeacon->cbProcessed)); 2515 //LogRel(("AudioTestBeaconAddConsecutive: Beacon proc finished (last was cbBuf=%RU32, fInBeacon=%RTbool, cbBeacon=%RU32, cbProc=%RU32)\n", cbBuf, fInBeacon, cbBeacon, pBeacon->cbProcessed)); 2516 #endif 2517 2518 Assert(pBeacon->cbProcessed >= cbProcessedInitial); 2519 return pBeacon->cbProcessed - cbProcessedInitial; 2520 } 2521 2522 /** 2523 * Returns whether a beacon is considered to be complete or not. 2524 * 2525 * A complete beacon means that all data for it has been retrieved. 2526 * 2527 * @returns \c true if complete, or \c false if not. 2528 * @param pBeacon Beacon to get completion status for. 2529 */ 2530 bool AudioTestBeaconIsComplete(PCAUDIOTESTTONEBEACON pBeacon) 2531 { 2532 AssertReturn(pBeacon->cbProcessed <= pBeacon->cbToProcess, true); 2533 return (pBeacon->cbProcessed == pBeacon->cbToProcess); 2534 } 2535 2536 /** 2324 2537 * Verifies a pre/post beacon of a test tone. 2325 2538 * 2326 2539 * @returns VBox status code, VERR_NOT_FOUND if beacon was not found. 2327 2540 * @param pVerJob Verification job to verify PCM data for. 2541 * @param fIn Set to \c true for recording, \c false for playback. 2328 2542 * @param fPre Set to \c true to verify a pre beacon, or \c false to verify a post beacon. 2329 2543 * @param pCmp File comparison parameters to file to verify beacon for. … … 2332 2546 */ 2333 2547 static int audioTestToneVerifyBeacon(PAUDIOTESTVERIFYJOB pVerJob, 2334 bool fPre, PAUDIOTESTFILECMPPARMS pCmp, PAUDIOTESTTONEPARMS pToneParms, uint64_t *puOff) 2548 bool fIn, bool fPre, PAUDIOTESTFILECMPPARMS pCmp, PAUDIOTESTTONEPARMS pToneParms, 2549 uint64_t *puOff) 2335 2550 { 2336 2551 int rc = RTFileSeek(pCmp->hFile, pCmp->offStart, RTFILE_SEEK_BEGIN, NULL); 2337 2552 AssertRCReturn(rc, rc); 2553 2554 AUDIOTESTTONEBEACON Beacon; 2555 AudioTestBeaconInit(&Beacon, 2556 fIn 2557 ? (fPre ? AUDIOTESTTONEBEACONTYPE_PLAY_PRE : AUDIOTESTTONEBEACONTYPE_PLAY_POST) 2558 : (fPre ? AUDIOTESTTONEBEACONTYPE_REC_PRE : AUDIOTESTTONEBEACONTYPE_REC_POST), &pToneParms->Props); 2559 2560 LogRel2(("Verifying %s beacon @ %RU64\n", AudioTestBeaconTypeGetName(Beacon.enmType), pCmp->offStart)); 2338 2561 2339 2562 uint8_t auBuf[64]; 2340 2563 uint64_t cbToCompare = pCmp->cbSize; 2341 uint32_t const cbFrameSize = PDMAudioPropsFrameSize(&pToneParms->Props); /* Use the audio frame size as chunk size. */ 2342 bool fInBeacon = false; 2343 uint32_t cbBeacon = 0; 2344 size_t offLastBeacon = 0; /* Offset (in bytes) of last beacon read. */ 2345 2346 uint8_t const byBeacon = fPre ? AUDIOTEST_BEACON_BYTE_PRE : AUDIOTEST_BEACON_BYTE_POST; 2347 2348 AssertReturn(cbFrameSize == 4, VERR_NOT_SUPPORTED); /* Otherwise the stuff below won't work. */ 2564 uint32_t const cbFrameSize = PDMAudioPropsFrameSize(&Beacon.Props); 2565 uint64_t offBeaconLast = 0; 2349 2566 2350 2567 /* Slow as heck, but does the job for now. */ … … 2358 2575 break; 2359 2576 2360 for (size_t i = 0; i < cbRead; i += cbFrameSize) 2361 { 2362 if ( auBuf[i] == byBeacon 2363 && auBuf[i + 1] == byBeacon 2364 && auBuf[i + 2] == byBeacon 2365 && auBuf[i + 3] == byBeacon) 2366 { 2367 if (!fInBeacon) 2368 { 2369 cbBeacon = 0; 2370 fInBeacon = true; 2371 } 2372 cbBeacon += cbFrameSize; 2373 } 2374 else 2375 { 2376 if (fInBeacon) 2377 { 2378 fInBeacon = false; 2379 offLastBeacon = RTFileTell(pCmp->hFile); 2380 continue; 2381 } 2382 } 2383 } 2384 2577 const uint32_t cbAdded = AudioTestBeaconAddConsecutive(&Beacon, auBuf, cbRead); 2578 if (cbAdded) 2579 offBeaconLast = RTFileTell(pCmp->hFile); 2580 2581 Assert(cbToCompare >= cbRead); 2385 2582 cbToCompare -= cbRead; 2386 2583 } 2387 2584 2388 uint32_t const cbBeacon Expected = PDMAudioPropsFramesToBytes(&pToneParms->Props, AUDIOTEST_BEACON_SIZE_FRAMES);2389 bool const fValid = cbBeacon == cbBeaconExpected; 2390 if (! fValid)2585 uint32_t const cbBeacon = AudioTestBeaconGetUsed(&Beacon); 2586 2587 if (!AudioTestBeaconIsComplete(&Beacon)) 2391 2588 { 2392 2589 int rc2 = audioTestErrorDescAddError(pVerJob->pErr, pVerJob->idxTest, "File '%s': %s beacon %s (got %RU32 bytes, expected %RU32)", 2393 2590 pCmp->pszName, 2394 fPre ? "Pre" : "Post", cbBeacon ? "found" : "not found", cbBeacon, cbBeaconExpected); 2591 AudioTestBeaconTypeGetName(Beacon.enmType), 2592 cbBeacon ? "found" : "not found", cbBeacon, 2593 AudioTestBeaconGetSize(&Beacon)); 2395 2594 AssertRC(rc2); 2396 2595 return VERR_NOT_FOUND; … … 2398 2597 else 2399 2598 { 2400 int rc2 = audioTestErrorDescAddInfo(pVerJob->pErr, pVerJob->idxTest, "File '%s': %s beacon found and valid", 2401 pCmp->pszName, fPre ? "Pre" : "Post"); 2599 AssertReturn(AudioTestBeaconGetRemaining(&Beacon) == 0, VERR_INTERNAL_ERROR); 2600 AssertReturn(offBeaconLast >= AudioTestBeaconGetSize(&Beacon), VERR_INTERNAL_ERROR); 2601 2602 int rc2 = audioTestErrorDescAddInfo(pVerJob->pErr, pVerJob->idxTest, "File '%s': %s beacon found at offset %RU64 and valid", 2603 pCmp->pszName, AudioTestBeaconTypeGetName(Beacon.enmType), 2604 offBeaconLast - AudioTestBeaconGetSize(&Beacon)); 2402 2605 AssertRC(rc2); 2403 2606 2404 2607 if (puOff) 2405 *puOff = off LastBeacon;2608 *puOff = offBeaconLast; 2406 2609 } 2407 2610 … … 2552 2755 2553 2756 uint64_t offBeaconAbs; 2554 rc = audioTestToneVerifyBeacon(pVerJob, true /* fPre */, &FileA, &ToneParmsA, &offBeaconAbs); 2757 rc = audioTestToneVerifyBeacon(pVerJob, phTestA->enmTestType == AUDIOTESTTYPE_TESTTONE_PLAY /* fIn */, 2758 true /* fPre */, &FileA, &ToneParmsA, &offBeaconAbs); 2555 2759 if (RT_SUCCESS(rc)) 2556 2760 { 2557 2761 FileA.offStart = offBeaconAbs; 2558 2762 FileA.cbSize = cbFileSizeA - FileA.offStart; 2559 rc = audioTestToneVerifyBeacon(pVerJob, false /* fPost */, &FileA, &ToneParmsA, NULL); 2560 } 2561 2562 rc = audioTestToneVerifyBeacon(pVerJob, true /* fPre */, &FileB, &ToneParmsB, &offBeaconAbs); 2763 rc = audioTestToneVerifyBeacon(pVerJob, phTestA->enmTestType == AUDIOTESTTYPE_TESTTONE_PLAY /* fIn */, 2764 false /* fPre */, &FileA, &ToneParmsA, NULL); 2765 } 2766 2767 rc = audioTestToneVerifyBeacon(pVerJob, phTestB->enmTestType == AUDIOTESTTYPE_TESTTONE_RECORD /* fIn */, 2768 true /* fPre */, &FileB, &ToneParmsB, &offBeaconAbs); 2563 2769 if (RT_SUCCESS(rc)) 2564 2770 { 2565 2771 FileB.offStart = offBeaconAbs; 2566 2772 FileB.cbSize = cbFileSizeB - FileB.offStart; 2567 rc = audioTestToneVerifyBeacon(pVerJob, false /* fPost */, &FileB, &ToneParmsB, NULL); 2773 rc = audioTestToneVerifyBeacon(pVerJob, phTestB->enmTestType == AUDIOTESTTYPE_TESTTONE_RECORD /* fIn */, 2774 false /* fPre */, &FileB, &ToneParmsB, NULL); 2568 2775 } 2569 2776 … … 2731 2938 CHECK_RC_MSG_MAYBE_RET(rc, pVerJob, "Test B not found"); 2732 2939 2733 AUDIOTESTTYPE enmTestTypeA = AUDIOTESTTYPE_INVALID; 2734 rc = audioTestObjGetUInt32(&hTestA, "test_type", (uint32_t *)&enmTestTypeA); 2940 rc = audioTestObjGetUInt32(&hTestA, "test_type", (uint32_t *)&hTestA.enmTestType); 2735 2941 CHECK_RC_MSG_MAYBE_RET(rc, pVerJob, "Test type A not found"); 2736 2942 2737 AUDIOTESTTYPE enmTestTypeB = AUDIOTESTTYPE_INVALID; 2738 rc = audioTestObjGetUInt32(&hTestB, "test_type", (uint32_t *)&enmTestTypeB); 2943 rc = audioTestObjGetUInt32(&hTestB, "test_type", (uint32_t *)&hTestB.enmTestType); 2739 2944 CHECK_RC_MSG_MAYBE_RET(rc, pVerJob, "Test type B not found"); 2740 2945 2741 switch ( enmTestTypeA)2946 switch (hTestA.enmTestType) 2742 2947 { 2743 2948 case AUDIOTESTTYPE_TESTTONE_PLAY: 2744 2949 { 2745 if ( enmTestTypeB== AUDIOTESTTYPE_TESTTONE_RECORD)2950 if (hTestB.enmTestType == AUDIOTESTTYPE_TESTTONE_RECORD) 2746 2951 rc = audioTestVerifyTestTone(&VerJob, &hTestA, &hTestB); 2747 2952 else 2748 2953 rc = audioTestErrorDescAddError(pErrDesc, i, "Playback test types don't match (set A=%#x, set B=%#x)", 2749 enmTestTypeA, enmTestTypeB);2954 hTestA.enmTestType, hTestB.enmTestType); 2750 2955 break; 2751 2956 } … … 2753 2958 case AUDIOTESTTYPE_TESTTONE_RECORD: 2754 2959 { 2755 if ( enmTestTypeB== AUDIOTESTTYPE_TESTTONE_PLAY)2960 if (hTestB.enmTestType == AUDIOTESTTYPE_TESTTONE_PLAY) 2756 2961 rc = audioTestVerifyTestTone(&VerJob, &hTestB, &hTestA); 2757 2962 else 2758 2963 rc = audioTestErrorDescAddError(pErrDesc, i, "Recording test types don't match (set A=%#x, set B=%#x)", 2759 enmTestTypeA, enmTestTypeB);2964 hTestA.enmTestType, hTestB.enmTestType); 2760 2965 break; 2761 2966 } -
trunk/src/VBox/Devices/Audio/AudioTest.h
r91655 r92195 32 32 /** Prefix for audio test (set) directories. */ 33 33 #define AUDIOTEST_PATH_PREFIX_STR "vkat" 34 /** Audio beacon data (single byte) to use for the post beacon (intro). */ 35 #define AUDIOTEST_BEACON_BYTE_PRE 0x42 36 /** Audio beacon data (single byte) to use for the post beacon (outro). */ 37 #define AUDIOTEST_BEACON_BYTE_POST 0x24 34 /** Audio beacon data (single byte) to use for the playback pre beacon (intro). */ 35 #define AUDIOTEST_BEACON_BYTE_PLAY_PRE 0x42 36 /** Audio beacon data (single byte) to use for the playback post beacon (outro). */ 37 #define AUDIOTEST_BEACON_BYTE_PLAY_POST 0x24 38 /** Audio beacon data (single byte) to use for the recording pre beacon (intro). */ 39 #define AUDIOTEST_BEACON_BYTE_REC_PRE 0x75 40 /** Audio beacon data (single byte) to use for the recording post beacon (outro). */ 41 #define AUDIOTEST_BEACON_BYTE_REC_POST 0x57 38 42 /** Pre / post audio beacon size (in audio frames). */ 39 43 #define AUDIOTEST_BEACON_SIZE_FRAMES 1024 … … 116 120 /** Pointer to audio test tone parameters. */ 117 121 typedef AUDIOTESTTONEPARMS *PAUDIOTESTTONEPARMS; 122 123 /** 124 * Enumeration defining an audio test beacon type. 125 */ 126 typedef enum AUDIOTESTTONEBEACONTYPE 127 { 128 /** Invalid type. */ 129 AUDIOTESTTONEBEACONTYPE_INVALID = 0, 130 /** Playback beacon (pre). */ 131 AUDIOTESTTONEBEACONTYPE_PLAY_PRE = 1, 132 /** Playback beacon (post). */ 133 AUDIOTESTTONEBEACONTYPE_PLAY_POST = 2, 134 /** Recording beacon (pre). */ 135 AUDIOTESTTONEBEACONTYPE_REC_PRE = 3, 136 /** Recording beacon (post). */ 137 AUDIOTESTTONEBEACONTYPE_REC_POST = 4, 138 /** The usual 32-bit hack. */ 139 OTESTTONEBEACONTYPE_32BIT_HACK = 0x7fffffff 140 } AUDIOTESTTONEBEACONTYPE; 141 142 /** 143 * Structure defining an audio test tone beacon. 144 * 145 * This is being used for (optionally) marking beginning/ending of audio test data. 146 */ 147 typedef struct AUDIOTESTTONEBEACON 148 { 149 /** The beacon type. */ 150 AUDIOTESTTONEBEACONTYPE enmType; 151 /** PCM properties to use for this beacon. */ 152 PDMAUDIOPCMPROPS Props; 153 /** Beacon bytes to process. 154 * When doing test tone playback: Beacon bytes to write. 155 * When doing test tone recording: Beacon bytes to read. */ 156 uint32_t cbToProcess; 157 /** Beacon bytes already processed. 158 * When doing test tone playback: Beacon bytes written. 159 * When doing test tone recording: Beacon bytes read. */ 160 uint32_t cbProcessed; 161 } AUDIOTESTTONEBEACON; 162 /** Pointer to audio test tone beacon. */ 163 typedef AUDIOTESTTONEBEACON *PAUDIOTESTTONEBEACON; 164 /** Pointer (const) to audio test tone beacon. */ 165 typedef AUDIOTESTTONEBEACON const *PCAUDIOTESTTONEBEACON; 118 166 119 167 /** … … 310 358 int AudioTestToneGenerate(PAUDIOTESTTONE pTone, void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten); 311 359 360 void AudioTestBeaconInit(PAUDIOTESTTONEBEACON pBeacon, AUDIOTESTTONEBEACONTYPE enmType, PPDMAUDIOPCMPROPS pProps); 361 uint32_t AudioTestBeaconAddConsecutive(PAUDIOTESTTONEBEACON pBeacon, const uint8_t *auBuf, size_t cbBuf); 362 int AudioTestBeaconWrite(PAUDIOTESTTONEBEACON pBeacon, void *pvBuf, uint32_t cbBuf); 363 uint32_t AudioTestBeaconGetSize(PCAUDIOTESTTONEBEACON pBeacon); 364 const char *AudioTestBeaconTypeGetName(AUDIOTESTTONEBEACONTYPE enmType); 365 AUDIOTESTTONEBEACONTYPE AudioTestBeaconGetType(PCAUDIOTESTTONEBEACON pBeacon); 366 uint32_t AudioTestBeaconGetRemaining(PCAUDIOTESTTONEBEACON pBeacon); 367 uint32_t AudioTestBeaconGetUsed(PCAUDIOTESTTONEBEACON pBeacon); 368 bool AudioTestBeaconIsComplete(PCAUDIOTESTTONEBEACON pBeacon); 369 312 370 int AudioTestGenTag(char *pszTag, size_t cbTag); 313 371 -
trunk/src/VBox/Devices/Audio/DrvHostAudioValidationKit.cpp
r91908 r92195 72 72 typedef struct VALKITTESTTONEDATA 73 73 { 74 /* Test tone beacon to use. 75 * Will be re-used for pre/post beacons. */ 76 AUDIOTESTTONEBEACON Beacon; 74 77 union 75 78 { … … 80 83 /** How many bytes already written. */ 81 84 uint64_t cbWritten; 82 /** Size (in bytes) a single pre/post beacon is. */83 uint32_t cbBeacon;84 /** Beacon bytes to write. */85 uint32_t cbBeaconToWrite;86 /** Beacon bytes written. */87 uint32_t cbBeaconWritten;88 85 } Rec; 89 86 struct … … 102 99 103 100 /** 101 * Enumeration specifying an internal test state. 102 */ 103 typedef enum VALKITTESTSTATE 104 { 105 /** Test is initializing. */ 106 VALKITTESTSTATE_INIT = 0, 107 /** Test is in pre-run phase. */ 108 VALKITTESTSTATE_PRE, 109 /** Test is running */ 110 VALKITTESTSTATE_RUN, 111 /** Test is in post-run phase. */ 112 VALKITTESTSTATE_POST, 113 /** Test has been run. */ 114 VALKITTESTSTATE_DONE 115 } VALKITTESTSTATE; 116 117 /** 104 118 * Structure keeping a single Validation Kit test. 105 119 */ … … 112 126 /** Current test set entry to process. */ 113 127 PAUDIOTESTENTRY pEntry; 128 /** Current test state. */ 129 VALKITTESTSTATE enmState; 114 130 /** Current test object to process. */ 115 131 AUDIOTESTOBJ Obj; … … 200 216 201 217 /** 218 * Converts an internal test state enum value to a string. 219 * 220 * @returns Pointer to read-only internal test state string on success, 221 * "illegal" if invalid command value. 222 * @param enmState The state to convert. 223 */ 224 DECLINLINE(const char *) drvHostValKitTestStatusToStr(VALKITTESTSTATE enmState) 225 { 226 switch (enmState) 227 { 228 case VALKITTESTSTATE_INIT: return "init"; 229 case VALKITTESTSTATE_PRE: return "pre"; 230 case VALKITTESTSTATE_RUN: return "run"; 231 case VALKITTESTSTATE_POST: return "post"; 232 case VALKITTESTSTATE_DONE: return "done"; 233 /* no default: */ 234 break; 235 } 236 AssertMsgFailedReturn(("Invalid test state: #%x\n", enmState), "illegal"); 237 } 238 239 /** 202 240 * Unregisters a ValKit test, common code. 203 241 * … … 393 431 LogRel(("ValKit: %RU32 tests still registered total (%RU32 play, %RU32 record)\n", 394 432 pThis->cTestsTotal, pThis->cTestsPlay, pThis->cTestsRec)); 433 434 PVALKITTESTDATA pTst; 435 RTListForEach(&pThis->lstTestsRec, pTst, VALKITTESTDATA, Node) 436 { 437 if (pTst->enmState != VALKITTESTSTATE_DONE) 438 LogRel(("ValKit: Warning: Test #%RU32 not done yet (state is '%s')\n", 439 pTst->idxTest, drvHostValKitTestStatusToStr(pTst->enmState))); 440 } 395 441 396 442 if ( AudioTestSetIsRunning(pSet) … … 482 528 AssertPtrReturn(pTestData, VERR_NO_MEMORY); 483 529 530 pTestData->enmState = VALKITTESTSTATE_INIT; 531 484 532 memcpy(&pTestData->t.TestTone.Parms, pToneParms, sizeof(AUDIOTESTTONEPARMS)); 485 533 … … 494 542 pTestData->t.TestTone.Parms.msDuration); 495 543 496 /* We play a pre + post beacon before + after the actual test tone 497 * with exactly AUDIOTEST_BEACON_SIZE_FRAMES audio frames. */ 498 pTestData->t.TestTone.u.Rec.cbBeacon = PDMAudioPropsFramesToBytes(pProps, AUDIOTEST_BEACON_SIZE_FRAMES); 499 pTestData->t.TestTone.u.Rec.cbBeaconToWrite = pTestData->t.TestTone.u.Rec.cbBeacon; 544 /* We inject a pre + post beacon before + after the actual test tone. 545 * We always start with the pre beacon. */ 546 AudioTestBeaconInit(&pTestData->t.TestTone.Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_PRE, pProps); 500 547 501 548 int rc = RTCritSectEnter(&pThis->CritSect); … … 505 552 pThis->idxTest, pTestData->t.TestTone.Parms.msDuration, pTestData->t.TestTone.u.Rec.cbToWrite, 506 553 pToneParms->Hdr.idxSeq)); 507 if (pTestData->t.TestTone.u.Rec.cbBeaconToWrite) 508 { 509 LogRel2(("ValKit: Guest recording test #%RU32 includes 2 x %RU32 bytes of beacons\n", 510 pThis->idxTest, pTestData->t.TestTone.u.Rec.cbBeaconToWrite)); 511 512 pTestData->t.TestTone.u.Rec.cbToWrite += 2 /* Pre + Post */ * pTestData->t.TestTone.u.Rec.cbBeaconToWrite; 513 } 554 555 const uint32_t cbBeacon = AudioTestBeaconGetSize(&pTestData->t.TestTone.Beacon); 556 if (cbBeacon) 557 LogRel2(("ValKit: Guest recording test #%RU32 includes 2 x %RU32 bytes of pre/post beacons\n", 558 pThis->idxTest, cbBeacon)); 514 559 515 560 RTListAppend(&pThis->lstTestsRec, &pTestData->Node); … … 540 585 AssertPtrReturn(pTestData, VERR_NO_MEMORY); 541 586 587 pTestData->enmState = VALKITTESTSTATE_INIT; 588 542 589 memcpy(&pTestData->t.TestTone.Parms, pToneParms, sizeof(AUDIOTESTTONEPARMS)); 543 590 591 PPDMAUDIOPCMPROPS const pProps = &pTestData->t.TestTone.Parms.Props; 592 544 593 AssertReturn(pTestData->t.TestTone.Parms.msDuration, VERR_INVALID_PARAMETER); 545 AssertReturn(PDMAudioPropsAreValid( &pTestData->t.TestTone.Parms.Props), VERR_INVALID_PARAMETER);546 547 pTestData->t.TestTone.u.Play.cbToRead = PDMAudioPropsMilliToBytes( &pTestData->t.TestTone.Parms.Props,594 AssertReturn(PDMAudioPropsAreValid(pProps), VERR_INVALID_PARAMETER); 595 596 pTestData->t.TestTone.u.Play.cbToRead = PDMAudioPropsMilliToBytes(pProps, 548 597 pTestData->t.TestTone.Parms.msDuration); 549 uint32_t const cbBeacons = PDMAudioPropsFramesToBytes(&pTestData->t.TestTone.Parms.Props, 550 AUDIOTEST_BEACON_SIZE_FRAMES * 2 /* Pre + post beacon */); 551 pTestData->t.TestTone.u.Play.cbToRead += cbBeacons; 598 599 /* We play a pre + post beacon before + after the actual test tone. 600 * We always start with the pre beacon. */ 601 AudioTestBeaconInit(&pTestData->t.TestTone.Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_PRE, pProps); 552 602 553 603 int rc = RTCritSectEnter(&pThis->CritSect); … … 557 607 pThis->idxTest, pTestData->t.TestTone.Parms.msDuration, pTestData->t.TestTone.u.Play.cbToRead, 558 608 pToneParms->Hdr.idxSeq)); 609 610 const uint32_t cbBeacon = AudioTestBeaconGetSize(&pTestData->t.TestTone.Beacon); 611 if (cbBeacon) 612 LogRel2(("ValKit: Guest playback test #%RU32 includes 2 x %RU32 bytes of pre/post beacons\n", 613 pThis->idxTest, cbBeacon)); 559 614 560 615 RTListAppend(&pThis->lstTestsPlay, &pTestData->Node); … … 824 879 825 880 if ( pTst 826 && pTst-> pEntry == NULL) /* Test not started yet? */881 && pTst->enmState == VALKITTESTSTATE_INIT) /* Test not started yet? */ 827 882 { 828 883 AUDIOTESTPARMS Parms; … … 847 902 char szTimeCreated[RTTIME_STR_LEN]; 848 903 RTTimeToString(&Parms.TestTone.Hdr.tsCreated, szTimeCreated, sizeof(szTimeCreated)); 849 LogRel (("ValKit: Test created (caller UTC): %s\n", szTimeCreated));904 LogRel2(("ValKit: Test created (caller UTC): %s\n", szTimeCreated)); 850 905 } 851 906 852 907 pStrmValKit->cbAvail += pTst->t.TestTone.u.Rec.cbToWrite; 853 LogRel(("ValKit: Now total of %RU32 bytes available for capturing\n", pStrmValKit->cbAvail)); 908 pStrmValKit->cbAvail += AudioTestBeaconGetSize(&pTst->t.TestTone.Beacon); /* Add beacon data, if any. */ 909 LogRel2(("ValKit: Now total of %RU32 bytes available for capturing\n", pStrmValKit->cbAvail)); 910 911 pTst->enmState = VALKITTESTSTATE_PRE; 854 912 } 855 913 … … 926 984 #endif 927 985 928 bool const fIsSilence = PDMAudioPropsIsBufferSilence(&pStream->pStream->Cfg.Props, pvBuf, cbBuf); 929 930 LogRel2(("ValKit: Playing stream '%s' (%RU32 bytes / %RU64ms -- %RU64 bytes / %RU64ms total so far) ...\n", 986 /* Flag indicating whether the whole block we're going to play is silence or not. */ 987 bool const fIsAllSilence = PDMAudioPropsIsBufferSilence(&pStream->pStream->Cfg.Props, pvBuf, cbBuf); 988 989 LogRel3(("ValKit: Playing stream '%s' (%RU32 bytes / %RU64ms -- %RU64 bytes / %RU64ms total so far) ...\n", 931 990 pStream->pStream->Cfg.szName, 932 991 cbBuf, PDMAudioPropsBytesToMilli(&pStream->pStream->Cfg.Props, cbBuf), … … 966 1025 } 967 1026 968 if (fIs Silence)1027 if (fIsAllSilence) 969 1028 { 970 1029 pThis->cbPlayedSilence += cbBuf; … … 978 1037 } 979 1038 980 bool fHandleSilence = true; 981 982 if (pTst->pEntry == NULL) /* Test not started yet? */ 1039 if (pTst->enmState == VALKITTESTSTATE_INIT) /* Test not started yet? */ 983 1040 { 984 1041 AUDIOTESTPARMS Parms; … … 1003 1060 RTTimeToString(&Parms.TestTone.Hdr.tsCreated, szTimeCreated, sizeof(szTimeCreated)); 1004 1061 LogRel(("ValKit: Test created (caller UTC): %s\n", szTimeCreated)); 1062 1063 pTst->enmState = VALKITTESTSTATE_PRE; 1005 1064 } 1006 1065 } … … 1010 1069 if (RT_SUCCESS(rc)) 1011 1070 { 1012 if ( !fIsSilence 1013 || (fIsSilence && fHandleSilence)) 1014 { 1015 rc = AudioTestObjWrite(pTst->Obj, pvBuf, cbBuf); 1016 pTst->t.TestTone.u.Play.cbRead += cbBuf; 1017 1018 const bool fComplete = pTst->t.TestTone.u.Play.cbRead >= pTst->t.TestTone.u.Play.cbToRead; 1019 if (fComplete) 1071 /* Always write (record) everything, no matter if the current audio contains complete silence or not. 1072 * Might be also become handy later if we want to have a look at start/stop timings and so on. */ 1073 rc = AudioTestObjWrite(pTst->Obj, pvBuf, cbBuf); 1074 1075 switch (pTst->enmState) 1076 { 1077 case VALKITTESTSTATE_PRE: 1078 RT_FALL_THROUGH(); 1079 case VALKITTESTSTATE_POST: 1020 1080 { 1021 LogRel(("ValKit: Test #%RU32: Recording audio data ended (took %RU32ms)\n", 1022 pTst->idxTest, RTTimeMilliTS() - pTst->msStartedTS)); 1023 1024 if (pTst->t.TestTone.u.Play.cbRead > pTst->t.TestTone.u.Play.cbToRead) 1025 LogRel(("ValKit: Warning: Test #%RU32 read %RU32 bytes more than announced\n", 1026 pTst->idxTest, pTst->t.TestTone.u.Play.cbRead - pTst->t.TestTone.u.Play.cbToRead)); 1027 1028 AudioTestSetTestDone(pTst->pEntry); 1029 1030 rc = RTCritSectEnter(&pThis->CritSect); 1031 if (RT_SUCCESS(rc)) 1081 PAUDIOTESTTONEBEACON pBeacon = &pTst->t.TestTone.Beacon; 1082 if ( AudioTestBeaconGetSize(pBeacon) 1083 && !AudioTestBeaconIsComplete(pBeacon)) 1032 1084 { 1033 drvHostValKiUnregisterPlayTest(pThis, pTst); 1034 1035 pThis->pTestCurPlay = NULL; 1036 pTst = NULL; 1037 1038 rc2 = RTCritSectLeave(&pThis->CritSect); 1039 if (RT_SUCCESS(rc)) 1040 rc = rc2; 1085 bool const fStarted = AudioTestBeaconGetRemaining(pBeacon) == AudioTestBeaconGetSize(pBeacon); 1086 1087 uint32_t const cbToAddMax = RT_MIN(cbBuf, AudioTestBeaconGetRemaining(pBeacon)); 1088 1089 AudioTestBeaconAddConsecutive(pBeacon, (uint8_t *)pvBuf, cbToAddMax); 1090 1091 if (fStarted) 1092 LogRel2(("ValKit: Test #%RU32: Detection of %s playback beacon started (%RU32ms played so far)\n", 1093 pTst->idxTest, AudioTestBeaconTypeGetName(pBeacon->enmType), 1094 PDMAudioPropsBytesToMilli(&pStream->pStream->Cfg.Props, pThis->cbPlayedTotal))); 1095 if (AudioTestBeaconIsComplete(pBeacon)) 1096 { 1097 LogRel2(("ValKit: Test #%RU32: Detection of %s playback beacon ended\n", 1098 pTst->idxTest, AudioTestBeaconTypeGetName(pBeacon->enmType))); 1099 1100 if (pTst->enmState == VALKITTESTSTATE_PRE) 1101 pTst->enmState = VALKITTESTSTATE_RUN; 1102 else if (pTst->enmState == VALKITTESTSTATE_POST) 1103 pTst->enmState = VALKITTESTSTATE_DONE; 1104 } 1041 1105 } 1106 1107 break; 1042 1108 } 1109 1110 case VALKITTESTSTATE_RUN: 1111 { 1112 /* Whether we count all silence as recorded data or not. 1113 * Currently we don't, as otherwise consequtively played tones will be cut off in the end. */ 1114 bool const fCountAllSilenceAsData = false; 1115 if ( !fIsAllSilence 1116 || (fIsAllSilence == fCountAllSilenceAsData)) 1117 pTst->t.TestTone.u.Play.cbRead += cbBuf; 1118 1119 const bool fComplete = pTst->t.TestTone.u.Play.cbRead >= pTst->t.TestTone.u.Play.cbToRead; 1120 if (fComplete) 1121 { 1122 LogRel(("ValKit: Test #%RU32: Recording audio data ended (took %RU32ms)\n", 1123 pTst->idxTest, RTTimeMilliTS() - pTst->msStartedTS)); 1124 1125 if (pTst->t.TestTone.u.Play.cbRead > pTst->t.TestTone.u.Play.cbToRead) 1126 LogRel(("ValKit: Warning: Test #%RU32 read %RU32 bytes more than announced\n", 1127 pTst->idxTest, pTst->t.TestTone.u.Play.cbRead - pTst->t.TestTone.u.Play.cbToRead)); 1128 1129 pTst->enmState = VALKITTESTSTATE_POST; 1130 /* Re-use the beacon object, but this time it's the post beacon. */ 1131 AudioTestBeaconInit(&pTst->t.TestTone.Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_POST, &pTst->t.TestTone.Parms.Props); 1132 } 1133 break; 1134 } 1135 1136 case VALKITTESTSTATE_DONE: 1137 { 1138 /* Handled below. */ 1139 break; 1140 } 1141 1142 default: 1143 AssertFailed(); 1144 break; 1043 1145 } 1044 1146 1045 1147 /* Always report everything as being played. */ 1046 1148 cbWritten = cbBuf; 1149 } 1150 1151 if (pTst->enmState == VALKITTESTSTATE_DONE) 1152 { 1153 AudioTestSetTestDone(pTst->pEntry); 1154 1155 rc = RTCritSectEnter(&pThis->CritSect); 1156 if (RT_SUCCESS(rc)) 1157 { 1158 drvHostValKiUnregisterPlayTest(pThis, pTst); 1159 1160 pThis->pTestCurPlay = NULL; 1161 pTst = NULL; 1162 1163 rc2 = RTCritSectLeave(&pThis->CritSect); 1164 if (RT_SUCCESS(rc)) 1165 rc = rc2; 1166 } 1047 1167 } 1048 1168 … … 1080 1200 PVALKITTESTDATA pTst = NULL; 1081 1201 1082 LogRel 2(("ValKit: Capturing stream '%s' (%RU32 bytes / %RU64ms -- %RU64 bytes / %RU64ms total so far) ...\n",1202 LogRel3(("ValKit: Capturing stream '%s' (%RU32 bytes / %RU64ms -- %RU64 bytes / %RU64ms total so far) ...\n", 1083 1203 pStream->pStream->Cfg.szName, 1084 1204 cbBuf, PDMAudioPropsBytesToMilli(&pStream->pStream->Cfg.Props, cbBuf), … … 1118 1238 uint32_t cbWritten = 0; 1119 1239 1120 /* Start playing the post beacon? */ 1121 if (pTst->t.TestTone.u.Rec.cbWritten == pTst->t.TestTone.u.Rec.cbToWrite - pTst->t.TestTone.u.Rec.cbBeaconToWrite) 1122 pTst->t.TestTone.u.Rec.cbBeaconWritten = 0; 1123 1124 /* Any beacon to write? */ 1125 if ( pTst->t.TestTone.u.Rec.cbBeaconToWrite 1126 && pTst->t.TestTone.u.Rec.cbBeaconWritten < pTst->t.TestTone.u.Rec.cbBeaconToWrite) 1127 { 1128 /* Limit to exactly one beacon (pre or post). */ 1129 uint32_t const cbToWrite = RT_MIN(cbBuf, 1130 pTst->t.TestTone.u.Rec.cbBeaconToWrite - pTst->t.TestTone.u.Rec.cbBeaconWritten); 1131 memset(pvBuf, 1132 pTst->t.TestTone.u.Rec.cbWritten >= pTst->t.TestTone.u.Rec.cbToWrite - pTst->t.TestTone.u.Rec.cbBeaconToWrite 1133 ? AUDIOTEST_BEACON_BYTE_POST : AUDIOTEST_BEACON_BYTE_PRE, 1134 cbToWrite); 1135 1136 cbWritten = cbToWrite; 1137 1138 pTst->t.TestTone.u.Rec.cbBeaconWritten += cbWritten; 1139 Assert(pTst->t.TestTone.u.Rec.cbBeaconWritten <= pTst->t.TestTone.u.Rec.cbBeaconToWrite); 1140 1141 rc = VINF_SUCCESS; 1142 } 1143 else 1144 { 1145 uint32_t const cbToWrite = RT_MIN(cbBuf, 1146 (pTst->t.TestTone.u.Rec.cbToWrite - pTst->t.TestTone.u.Rec.cbBeaconToWrite) 1147 - pTst->t.TestTone.u.Rec.cbWritten); 1148 if (cbToWrite) 1149 rc = AudioTestToneGenerate(&pTst->t.TestTone.Tone, pvBuf, cbToWrite, &cbWritten); 1150 if ( RT_SUCCESS(rc) 1151 && cbWritten) 1152 { 1153 Assert(cbWritten == cbToWrite); 1154 1155 if (cbWritten > pStrmValKit->cbAvail) 1156 LogRel(("ValKit: Warning: Test #%RU32: Reading more from capturing stream than availabe for (%RU32 vs. %RU32)\n", 1157 pTst->idxTest, cbWritten, pStrmValKit->cbAvail)); 1158 } 1159 } 1160 1161 if (RT_SUCCESS(rc)) 1162 { 1163 rc = AudioTestObjWrite(pTst->Obj, pvBuf, cbWritten); 1164 if (RT_SUCCESS(rc)) 1165 { 1166 pThis->cbRecordedTotal += cbWritten; /* Do a bit of accounting. */ 1167 1168 pStrmValKit->cbAvail -= RT_MIN(pStrmValKit->cbAvail, cbWritten); 1169 1170 pTst->t.TestTone.u.Rec.cbWritten += cbWritten; 1171 Assert(pTst->t.TestTone.u.Rec.cbWritten <= pTst->t.TestTone.u.Rec.cbToWrite); 1172 1173 LogRel(("ValKit: Test #%RU32: Supplied %RU32 bytes of (capturing) audio data (%RU32 bytes left)\n", 1174 pTst->idxTest, cbWritten, pStrmValKit->cbAvail)); 1240 switch (pTst->enmState) 1241 { 1242 case VALKITTESTSTATE_PRE: 1243 RT_FALL_THROUGH(); 1244 case VALKITTESTSTATE_POST: 1245 { 1246 PAUDIOTESTTONEBEACON pBeacon = &pTst->t.TestTone.Beacon; 1247 if ( AudioTestBeaconGetSize(pBeacon) 1248 && !AudioTestBeaconIsComplete(pBeacon)) 1249 { 1250 bool const fStarted = AudioTestBeaconGetRemaining(pBeacon) == AudioTestBeaconGetSize(pBeacon); 1251 1252 uint32_t const cbBeaconRemaining = AudioTestBeaconGetRemaining(pBeacon); 1253 AssertBreakStmt(cbBeaconRemaining, VERR_WRONG_ORDER); 1254 1255 /* Limit to exactly one beacon (pre or post). */ 1256 uint32_t const cbToWrite = RT_MIN(cbBuf, cbBeaconRemaining); 1257 1258 rc = AudioTestBeaconWrite(pBeacon, pvBuf, cbToWrite); 1259 if (RT_SUCCESS(rc)) 1260 cbWritten = cbToWrite; 1261 1262 if (fStarted) 1263 LogRel2(("ValKit: Test #%RU32: Writing %s beacon begin\n", 1264 pTst->idxTest, AudioTestBeaconTypeGetName(pBeacon->enmType))); 1265 if (AudioTestBeaconIsComplete(pBeacon)) 1266 { 1267 LogRel2(("ValKit: Test #%RU32: Writing %s beacon end\n", 1268 pTst->idxTest, AudioTestBeaconTypeGetName(pBeacon->enmType))); 1269 1270 if (pTst->enmState == VALKITTESTSTATE_PRE) 1271 pTst->enmState = VALKITTESTSTATE_RUN; 1272 else if (pTst->enmState == VALKITTESTSTATE_POST) 1273 pTst->enmState = VALKITTESTSTATE_DONE; 1274 } 1275 } 1276 break; 1277 } 1278 1279 case VALKITTESTSTATE_RUN: 1280 { 1281 uint32_t const cbToWrite = RT_MIN(cbBuf, pTst->t.TestTone.u.Rec.cbToWrite - pTst->t.TestTone.u.Rec.cbWritten); 1282 if (cbToWrite) 1283 rc = AudioTestToneGenerate(&pTst->t.TestTone.Tone, pvBuf, cbToWrite, &cbWritten); 1284 if ( RT_SUCCESS(rc) 1285 && cbWritten) 1286 { 1287 Assert(cbWritten == cbToWrite); 1288 1289 if (cbWritten > pStrmValKit->cbAvail) 1290 LogRel(("ValKit: Warning: Test #%RU32: Reading more from capturing stream than availabe for (%RU32 vs. %RU32)\n", 1291 pTst->idxTest, cbWritten, pStrmValKit->cbAvail)); 1292 1293 pTst->t.TestTone.u.Rec.cbWritten += cbWritten; 1294 } 1295 1296 LogRel3(("ValKit: Test #%RU32: Supplied %RU32 bytes of (capturing) audio data (%RU32 bytes left)\n", 1297 pTst->idxTest, cbWritten, pStrmValKit->cbAvail)); 1175 1298 1176 1299 const bool fComplete = pTst->t.TestTone.u.Rec.cbWritten >= pTst->t.TestTone.u.Rec.cbToWrite; … … 1180 1303 pTst->idxTest, RTTimeMilliTS() - pTst->msStartedTS)); 1181 1304 1182 AudioTestSetTestDone(pTst->pEntry); 1183 1184 rc = RTCritSectEnter(&pThis->CritSect); 1185 if (RT_SUCCESS(rc)) 1186 { 1187 drvHostValKiUnregisterRecTest(pThis, pTst); 1188 1189 pThis->pTestCurRec = NULL; 1190 pTst = NULL; 1191 1192 int rc2 = RTCritSectLeave(&pThis->CritSect); 1193 AssertRC(rc2); 1194 } 1305 pTst->enmState = VALKITTESTSTATE_POST; 1306 /* Re-use the beacon object, but this time it's the post beacon. */ 1307 AudioTestBeaconInit(&pTst->t.TestTone.Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_POST, &pTst->t.TestTone.Parms.Props); 1308 pStrmValKit->cbAvail += AudioTestBeaconGetSize(&pTst->t.TestTone.Beacon); 1195 1309 } 1310 break; 1311 } 1312 1313 case VALKITTESTSTATE_DONE: 1314 { 1315 /* Handled below. */ 1316 break; 1317 } 1318 1319 default: 1320 AssertFailed(); 1321 break; 1322 } 1323 1324 if (RT_SUCCESS(rc)) 1325 { 1326 rc = AudioTestObjWrite(pTst->Obj, pvBuf, cbWritten); 1327 if (RT_SUCCESS(rc)) 1328 pStrmValKit->cbAvail -= RT_MIN(pStrmValKit->cbAvail, cbWritten); 1329 } 1330 1331 if (pTst->enmState == VALKITTESTSTATE_DONE) 1332 { 1333 AudioTestSetTestDone(pTst->pEntry); 1334 1335 rc = RTCritSectEnter(&pThis->CritSect); 1336 if (RT_SUCCESS(rc)) 1337 { 1338 drvHostValKiUnregisterRecTest(pThis, pTst); 1339 1340 pThis->pTestCurRec = NULL; 1341 pTst = NULL; 1342 1343 int rc2 = RTCritSectLeave(&pThis->CritSect); 1344 AssertRC(rc2); 1196 1345 } 1197 1346 } … … 1203 1352 LogRel(("ValKit: Test #%RU32: Failed with %Rrc\n", pTst->idxTest, rc)); 1204 1353 } 1354 1355 pThis->cbRecordedTotal += cbWritten; /* Do a bit of accounting. */ 1205 1356 1206 1357 *pcbRead = cbWritten; -
trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp
r92058 r92195 525 525 uint32_t cbPlayedTotal = 0; 526 526 527 /* We play a pre + post beacon before + after the actual test tone 528 * with exactly AUDIOTEST_BEACON_SIZE_FRAMES audio frames. */529 uint32_t const cbBeacon = PDMAudioPropsFramesToBytes(&pStream->Cfg.Props, AUDIOTEST_BEACON_SIZE_FRAMES);530 uint32_t cbBeaconToPlay = cbBeacon;531 uint32_t cbBeaconPlayed = 0; 532 527 /* We play a pre + post beacon before + after the actual test tone. 528 * We always start with the pre beacon. */ 529 AUDIOTESTTONEBEACON Beacon; 530 AudioTestBeaconInit(&Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_PRE, &pStream->Cfg.Props); 531 532 uint32_t const cbBeacon = AudioTestBeaconGetSize(&Beacon); 533 533 if (cbBeacon) 534 534 { 535 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing 2 x %RU32 bytes pre/post beacons\n", cbBeacon ToPlay);535 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing 2 x %RU32 bytes pre/post beacons\n", cbBeacon); 536 536 cbToPlayTotal += cbBeacon * 2 /* Pre + post beacon */; 537 537 } … … 539 539 if (pTstEnv) 540 540 { 541 AudioTestObjAddMetadataStr(Obj, "beacon_type=%RU32\n", (uint32_t)AudioTestBeaconGetType(&Beacon)); 541 542 AudioTestObjAddMetadataStr(Obj, "beacon_pre_bytes=%RU32\n", cbBeacon); 542 543 AudioTestObjAddMetadataStr(Obj, "beacon_post_bytes=%RU32\n", cbBeacon); … … 591 592 592 593 /* Any beacon to play? */ 593 if ( cbBeaconToPlay594 && cbBeaconPlayed < cbBeaconToPlay)594 uint32_t const cbBeaconRemaining = AudioTestBeaconGetRemaining(&Beacon); 595 if (cbBeaconRemaining) 595 596 { 596 597 /* Limit to exactly one beacon (pre or post). */ 597 cbToPlay = RT_MIN(sizeof(abBuf), RT_MIN(cbCanWrite, cbBeaconToPlay - cbBeaconPlayed)); 598 memset(abBuf, 599 cbPlayedTotal >= cbToPlayTotal - cbBeaconToPlay ? AUDIOTEST_BEACON_BYTE_POST : AUDIOTEST_BEACON_BYTE_PRE, 600 cbToPlay); 601 602 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToPlay, &cbPlayed); 598 cbToPlay = RT_MIN(sizeof(abBuf), RT_MIN(cbCanWrite, cbBeaconRemaining)); 599 rc = AudioTestBeaconWrite(&Beacon, abBuf, cbToPlay); 600 if (RT_SUCCESS(rc)) 601 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToPlay, &cbPlayed); 603 602 if (RT_FAILURE(rc)) 604 603 break; … … 611 610 rc = AudioTestObjWrite(Obj, abBuf, cbPlayed); 612 611 } 613 614 cbBeaconPlayed += cbPlayed;615 cbPlayedTotal += cbPlayed;616 continue;617 612 } 618 619 /* Start playing the post beacon? */ 620 if (cbPlayedTotal == cbToPlayTotal - cbBeaconToPlay) 613 else /* Play test tone */ 621 614 { 622 cbBeaconPlayed = 0; 623 continue; 624 } 625 626 if (RT_FAILURE(rc)) 627 break; 628 629 uint32_t const cbToGenerate = RT_MIN(RT_MIN(cbToPlayTotal - cbPlayedTotal - cbBeaconToPlay, sizeof(abBuf)), 630 cbCanWrite); 631 rc = AudioTestToneGenerate(&TstTone, abBuf, cbToGenerate, &cbToPlay); 632 if (RT_SUCCESS(rc)) 633 { 634 if (pTstEnv) 615 uint32_t const cbTestToneToPlay = cbToPlayTotal - cbPlayedTotal - (cbBeacon /* Pre / post beacon */); 616 if (cbTestToneToPlay == 0) /* Done playing the test tone? */ 635 617 { 636 /* Write stuff to disk before trying to play it. Help analysis later. */ 637 rc = AudioTestObjWrite(Obj, abBuf, cbToPlay); 618 if (AudioTestBeaconGetSize(&Beacon)) /* Play the post beacon, if any. */ 619 { 620 AudioTestBeaconInit(&Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_POST, &pStream->Cfg.Props); 621 continue; 622 } 623 624 break; 638 625 } 626 627 uint32_t const cbToGenerate = RT_MIN(RT_MIN(cbTestToneToPlay, sizeof(abBuf)), cbCanWrite); 628 rc = AudioTestToneGenerate(&TstTone, abBuf, cbToGenerate, &cbToPlay); 639 629 if (RT_SUCCESS(rc)) 640 630 { 641 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToPlay, &cbPlayed); 631 if (pTstEnv) 632 { 633 /* Write stuff to disk before trying to play it. Help analysis later. */ 634 rc = AudioTestObjWrite(Obj, abBuf, cbToPlay); 635 } 642 636 if (RT_SUCCESS(rc)) 643 637 { 644 AssertBreakStmt(cbPlayed <= cbToPlay, rc = VERR_TOO_MUCH_DATA); 645 646 offStream += cbPlayed; 647 648 if (cbPlayed != cbToPlay) 649 RTTestFailed(g_hTest, "Only played %RU32/%RU32 bytes", cbPlayed, cbToPlay); 650 651 if (cbPlayed) 652 nsLastWrite = nsNow; 638 rc = AudioTestMixStreamPlay(&pStream->Mix, abBuf, cbToPlay, &cbPlayed); 639 if (RT_SUCCESS(rc)) 640 { 641 AssertBreakStmt(cbPlayed <= cbToPlay, rc = VERR_TOO_MUCH_DATA); 642 643 offStream += cbPlayed; 644 645 if (cbPlayed != cbToPlay) 646 RTTestFailed(g_hTest, "Only played %RU32/%RU32 bytes", cbPlayed, cbToPlay); 647 648 if (cbPlayed) 649 nsLastWrite = nsNow; 650 } 653 651 } 654 652 } … … 746 744 if (RT_SUCCESS(rc)) 747 745 { 748 uint64_t cbToRecTotal = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, pParms->msDuration); 749 750 /* We record a pre + post beacon before + after the actual test tone 751 * with exactly AUDIOTEST_BEACON_SIZE_FRAMES audio frames. */ 752 uint32_t const cbBeacon = PDMAudioPropsFramesToBytes(&pStream->Cfg.Props, AUDIOTEST_BEACON_SIZE_FRAMES); 746 uint64_t cbRecTotal = 0; /* Counts everything, including silence / whatever. */ 747 uint64_t cbTestToRec = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, pParms->msDuration); 748 749 /* We expect a pre + post beacon before + after the actual test tone. 750 * We always start with the pre beacon. */ 751 AUDIOTESTTONEBEACON Beacon; 752 AudioTestBeaconInit(&Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_PRE, &pStream->Cfg.Props); 753 754 uint32_t const cbBeacon = AudioTestBeaconGetSize(&Beacon); 753 755 if (cbBeacon) 754 756 { 755 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, " Recording 2 x %RU32 bytes pre/post beacons\n", cbBeacon);756 cbT oRecTotal += cbBeacon * 2 /* Pre + post beacon */;757 758 AudioTestObjAddMetadataStr(Obj, "beacon_pre_bytes=%RU32\n", cbBeacon); 759 AudioTestObjAddMetadataStr(Obj, "beacon_post_bytes=%RU32\n", cbBeacon);760 }761 762 AudioTestObjAddMetadataStr(Obj, "stream_to_record_bytes=%RU32\n", cbT oRecTotal);757 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Expecting 2 x %RU32 bytes pre/post beacons\n", cbBeacon); 758 cbTestToRec = cbBeacon * 2 /* Pre + post beacon */; 759 } 760 761 AudioTestObjAddMetadataStr(Obj, "beacon_type=%RU32\n", (uint32_t)AudioTestBeaconGetType(&Beacon)); 762 AudioTestObjAddMetadataStr(Obj, "beacon_pre_bytes=%RU32\n", cbBeacon); 763 AudioTestObjAddMetadataStr(Obj, "beacon_post_bytes=%RU32\n", cbBeacon); 764 AudioTestObjAddMetadataStr(Obj, "stream_to_record_bytes=%RU32\n", cbTestToRec); 763 765 AudioTestObjAddMetadataStr(Obj, "stream_buffer_size_ms=%RU32\n", pIoOpts->cMsBufferSize); 764 766 AudioTestObjAddMetadataStr(Obj, "stream_prebuf_size_ms=%RU32\n", pIoOpts->cMsPreBuffer); … … 767 769 AudioTestObjAddMetadataStr(Obj, "device_scheduling_hint_ms=%RU32\n", pIoOpts->cMsSchedulingHint); 768 770 769 RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Recording %RU32 bytes total\n", cbT oRecTotal);771 RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Recording %RU32 bytes total\n", cbTestToRec); 770 772 771 773 uint8_t abSamples[16384]; 772 uint32_t const cbSamplesAligned = PDMAudioPropsFloorBytesToFrame(pMix->pProps, sizeof(abSamples));773 uint64_t cb RecTotal= 0;774 uint32_t const cbSamplesAligned = PDMAudioPropsFloorBytesToFrame(pMix->pProps, sizeof(abSamples)); 775 uint64_t cbTestRec = 0; 774 776 775 777 uint64_t const nsStarted = RTTimeNanoTS(); … … 778 780 uint64_t nsLastMsgCantRead = 0; /* Timestamp (in ns) when the last message of an unreadable stream was shown. */ 779 781 780 while (!g_fTerminate && cb RecTotal < cbToRecTotal)782 while (!g_fTerminate && cbTestRec < cbTestToRec) 781 783 { 782 784 uint64_t const nsNow = RTTimeNanoTS(); … … 799 801 if (cbRecorded) 800 802 { 803 cbRecTotal += cbRecorded; 804 801 805 rc = AudioTestObjWrite(Obj, abSamples, cbRecorded); 802 806 if (RT_SUCCESS(rc)) 803 807 { 804 cbRecTotal += cbRecorded; 805 806 /** @todo Clamp result? */ 808 if (AudioTestBeaconGetSize(&Beacon)) 809 { 810 if (!AudioTestBeaconIsComplete(&Beacon)) 811 { 812 bool const fStarted = AudioTestBeaconGetRemaining(&Beacon) == AudioTestBeaconGetSize(&Beacon); 813 814 uint32_t const cbToAddMax = RT_MIN(cbRecorded, AudioTestBeaconGetRemaining(&Beacon)); 815 816 uint32_t const cbAdded = AudioTestBeaconAddConsecutive(&Beacon, abSamples, cbToAddMax); 817 if (cbAdded) 818 cbTestRec += cbAdded; /* Only count data which belongs to a (complete test tone). */ 819 820 if ( fStarted 821 && g_uVerbosity >= 2) 822 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, 823 "Detection of %s playback beacon started (%RU32ms recorded so far)\n", 824 AudioTestBeaconTypeGetName(Beacon.enmType), 825 PDMAudioPropsBytesToMilli(&pStream->pStream->Cfg.Props, cbRecTotal)); 826 827 if (AudioTestBeaconIsComplete(&Beacon)) 828 { 829 if (g_uVerbosity >= 2) 830 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Detection of %s playback beacon ended\n", 831 AudioTestBeaconTypeGetName(Beacon.enmType)); 832 } 833 } 834 else 835 { 836 uint32_t const cbTestToneToRec = cbTestToRec - cbTestRec - cbBeacon; 837 if (cbTestToneToRec == 0) /* Done recording the test tone? */ 838 { 839 AudioTestBeaconInit(&Beacon, AUDIOTESTTONEBEACONTYPE_PLAY_POST, &pStream->Cfg.Props); 840 } 841 else /* Count test tone data. */ 842 cbTestRec += cbRecorded; 843 } 844 } 807 845 } 808 846 } … … 836 874 } 837 875 838 if (cb RecTotal != cbToRecTotal)839 RTTestFailed(g_hTest, "Recording ended unexpectedly (%RU32/%RU32 recorded)\n", cb RecTotal, cbToRecTotal);876 if (cbTestRec != cbTestToRec) 877 RTTestFailed(g_hTest, "Recording ended unexpectedly (%RU32/%RU32 recorded)\n", cbTestRec, cbTestToRec); 840 878 841 879 int rc2 = AudioTestMixStreamDisable(pMix);
Note:
See TracChangeset
for help on using the changeset viewer.