Changeset 90723 in vbox
- Timestamp:
- Aug 18, 2021 3:41:36 PM (3 years ago)
- Location:
- trunk/src/VBox/ValidationKit/utils/audio
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/audio/vkatCmdGeneric.cpp
r90087 r90723 31 31 #include <iprt/errcore.h> 32 32 #include <iprt/message.h> 33 #include <iprt/rand.h> 33 34 #include <iprt/test.h> 34 35 … … 366 367 } 367 368 369 /** 370 * Worker for audioTestCmdPlayHandler that plays one test tone. 371 */ 372 static RTEXITCODE audioTestPlayTestToneOne(PAUDIOTESTTONEPARMS pToneParms, 373 PCPDMDRVREG pDrvReg, const char *pszDevId, uint32_t cMsBufferSize, 374 uint32_t cMsPreBuffer, uint32_t cMsSchedulingHint, 375 uint8_t cChannels, uint8_t cbSample, uint32_t uHz, 376 bool fWithDrvAudio, bool fWithMixer) 377 { 378 char szTmp[128]; 379 380 AUDIOTESTSTREAM TstStream; 381 RT_ZERO(TstStream); 382 383 /* 384 * Construct the driver stack. 385 */ 386 RTEXITCODE rcExit = RTEXITCODE_FAILURE; 387 AUDIOTESTDRVSTACK DrvStack; 388 int rc = audioTestDriverStackInit(&DrvStack, pDrvReg, fWithDrvAudio); 389 if (RT_SUCCESS(rc)) 390 { 391 /* 392 * Set the output device if one is specified. 393 */ 394 rc = audioTestDriverStackSetDevice(&DrvStack, PDMAUDIODIR_OUT, pszDevId); 395 if (RT_SUCCESS(rc)) 396 { 397 /* 398 * Open a stream for the output. 399 */ 400 PDMAUDIOPCMPROPS ReqProps = pToneParms->Props; 401 if (cChannels != 0 && PDMAudioPropsChannels(&ReqProps) != cChannels) 402 PDMAudioPropsSetChannels(&ReqProps, cChannels); 403 if (cbSample != 0) 404 PDMAudioPropsSetSampleSize(&ReqProps, cbSample); 405 if (uHz != 0) 406 ReqProps.uHz = uHz; 407 408 rc = audioTestDriverStackStreamCreateOutput(&DrvStack, &ReqProps, cMsBufferSize, 409 cMsPreBuffer, cMsSchedulingHint, &TstStream.pStream, &TstStream.Cfg); 410 if (RT_SUCCESS(rc)) 411 { 412 /* 413 * Automatically enable the mixer if the wave file and the 414 * output parameters doesn't match. 415 */ 416 if ( !fWithMixer 417 && !PDMAudioPropsAreEqual(&pToneParms->Props, &TstStream.pStream->Cfg.Props)) 418 { 419 RTMsgInfo("Enabling the mixer buffer.\n"); 420 fWithMixer = true; 421 } 422 423 /* 424 * Create a mixer wrapper. This is just a thin wrapper if fWithMixer 425 * is false, otherwise it's doing mixing, resampling and recoding. 426 */ 427 rc = AudioTestMixStreamInit(&TstStream.Mix, &DrvStack, TstStream.pStream, fWithMixer ? &pToneParms->Props : NULL, 100 /*ms*/); 428 if (RT_SUCCESS(rc)) 429 { 430 if (g_uVerbosity > 0) 431 RTMsgInfo("Stream: %s cbBackend=%#RX32%s\n", 432 PDMAudioPropsToString(&TstStream.pStream->Cfg.Props, szTmp, sizeof(szTmp)), 433 TstStream.pStream->cbBackend, fWithMixer ? " mixed" : ""); 434 435 /* 436 * Enable the stream and start playing. 437 */ 438 rc = AudioTestMixStreamEnable(&TstStream.Mix); 439 if (RT_SUCCESS(rc)) 440 { 441 rc = audioTestPlayTone(NULL /* pTstEnv */, &TstStream, pToneParms); 442 if (RT_SUCCESS(rc)) 443 rcExit = RTEXITCODE_SUCCESS; 444 } 445 else 446 rcExit = RTMsgErrorExitFailure("Enabling the output stream failed: %Rrc", rc); 447 448 /* 449 * Clean up. 450 */ 451 AudioTestMixStreamTerm(&TstStream.Mix); 452 } 453 audioTestDriverStackStreamDestroy(&DrvStack, TstStream.pStream); 454 } 455 else 456 rcExit = RTMsgErrorExitFailure("Creating output stream failed: %Rrc", rc); 457 } 458 else 459 rcExit = RTMsgErrorExitFailure("Failed to set output device to '%s': %Rrc", pszDevId, rc); 460 audioTestDriverStackDelete(&DrvStack); 461 } 462 else 463 rcExit = RTMsgErrorExitFailure("Driver stack construction failed: %Rrc", rc); 464 return rcExit; 465 } 466 368 467 369 468 /** … … 377 476 { "--frequency", 'f', RTGETOPT_REQ_UINT32 }, 378 477 { "--sample-size", 'z', RTGETOPT_REQ_UINT8 }, 478 { "--test-tone", 't', RTGETOPT_REQ_NOTHING }, 379 479 { "--output-device", 'o', RTGETOPT_REQ_STRING }, 380 480 { "--with-drv-audio", 'd', RTGETOPT_REQ_NOTHING }, … … 388 488 switch (pOpt->iShort) 389 489 { 390 case 'b': return "The audio backend to use .";490 case 'b': return "The audio backend to use"; 391 491 case 'c': return "Number of backend output channels"; 392 case 'd': return "Go via DrvAudio instead of directly interfacing with the backend .";492 case 'd': return "Go via DrvAudio instead of directly interfacing with the backend"; 393 493 case 'f': return "Output frequency (Hz)"; 394 494 case 'z': return "Output sample size (bits)"; 395 case 'm': return "Go via the mixer."; 396 case 'o': return "The ID of the output device to use."; 495 case 't': return "Plays a test tone. Can be specified multiple times"; 496 case 'm': return "Go via the mixer"; 497 case 'o': return "The ID of the output device to use"; 397 498 default: return NULL; 398 499 } … … 416 517 bool fWithDrvAudio = false; 417 518 bool fWithMixer = false; 519 uint32_t cTestTones = 0; 418 520 uint8_t cbSample = 0; 419 521 uint8_t cChannels = 0; … … 453 555 break; 454 556 557 case 't': 558 cTestTones++; 559 break; 560 455 561 case 'z': 456 562 cbSample = ValueUnion.u8 / 8; … … 459 565 case VINF_GETOPT_NOT_OPTION: 460 566 { 567 if (cTestTones) 568 return RTMsgErrorExit(RTEXITCODE_SYNTAX, "Playing test tones (-t) cannot be combined with playing files"); 569 461 570 RTEXITCODE rcExit = audioTestPlayOne(ValueUnion.psz, pDrvReg, pszDevId, cMsBufferSize, cMsPreBuffer, 462 571 cMsSchedulingHint, cChannels, cbSample, uHz, fWithDrvAudio, fWithMixer); … … 472 581 } 473 582 } 583 584 while (cTestTones--) 585 { 586 AUDIOTESTTONEPARMS ToneParms; 587 RT_ZERO(ToneParms); 588 589 /* Use some sane defaults if no PCM props are set by the user. */ 590 PDMAudioPropsInit(&ToneParms.Props, 591 cbSample ? cbSample : 4, true /* fSigned */, cChannels ? cChannels : 2, uHz ? uHz : 44100); 592 593 ToneParms.dbFreqHz = AudioTestToneGetRandomFreq(); 594 ToneParms.msPrequel = 0; /** @todo Implement analyzing this first! */ 595 #ifdef DEBUG_andy 596 ToneParms.msDuration = RTRandU32Ex(50, 2500); 597 #else 598 ToneParms.msDuration = RTRandU32Ex(0, RT_MS_10SEC); /** @todo Probably a bit too long, but let's see. */ 599 #endif 600 ToneParms.msSequel = 0; /** @todo Implement analyzing this first! */ 601 ToneParms.uVolumePercent = 100; /** @todo Implement analyzing this first! */ 602 603 RTEXITCODE rcExit = audioTestPlayTestToneOne(&ToneParms, pDrvReg, pszDevId, cMsBufferSize, cMsPreBuffer, 604 cMsSchedulingHint, cChannels, cbSample, uHz, fWithDrvAudio, fWithMixer); 605 if (rcExit != RTEXITCODE_SUCCESS) 606 return rcExit; 607 } 608 474 609 return RTEXITCODE_SUCCESS; 475 610 } -
trunk/src/VBox/ValidationKit/utils/audio/vkatCommon.cpp
r90683 r90723 239 239 * @returns VBox status code. 240 240 * @param pTstEnv Test environment to use for running the test. 241 * Optional and can be NULL (for simple playback only). 241 242 * @param pStream Stream to use for playing the tone. 242 243 * @param pParms Tone parameters to use. … … 244 245 * @note Blocking function. 245 246 */ 246 staticint audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms)247 int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms) 247 248 { 248 249 AUDIOTESTTONE TstTone; 249 250 AudioTestToneInit(&TstTone, &pStream->Cfg.Props, pParms->dbFreqHz); 250 251 251 const char *pcszPathOut = pTstEnv->Set.szPathAbs; 252 char const *pcszPathOut = NULL; 253 if (pTstEnv) 254 pcszPathOut = pTstEnv->Set.szPathAbs; 252 255 253 256 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Playing test tone (tone frequency is %RU16Hz, %RU32ms)\n", (uint16_t)pParms->dbFreqHz, pParms->msDuration); 254 257 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Using %RU32ms stream scheduling hint\n", pStream->Cfg.Device.cMsSchedulingHint); 255 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Writing to '%s'\n", pcszPathOut); 258 if (pcszPathOut) 259 RTTestPrintf(g_hTest, RTTESTLVL_ALWAYS, "Writing to '%s'\n", pcszPathOut); 260 261 int rc; 256 262 257 263 /** @todo Use .WAV here? */ 258 264 AUDIOTESTOBJ Obj; 259 int rc = AudioTestSetObjCreateAndRegister(&pTstEnv->Set, "guest-tone-play.pcm", &Obj); 260 AssertRCReturn(rc, rc); 265 if (pTstEnv) 266 { 267 rc = AudioTestSetObjCreateAndRegister(&pTstEnv->Set, "guest-tone-play.pcm", &Obj); 268 AssertRCReturn(rc, rc); 269 } 261 270 262 271 rc = AudioTestMixStreamEnable(&pStream->Mix); … … 271 280 RTTestPrintf(g_hTest, RTTESTLVL_DEBUG, "Playing %RU32 bytes total\n", cbToPlayTotal); 272 281 273 AudioTestObjAddMetadataStr(Obj, "stream_to_play_bytes=%RU32\n", cbToPlayTotal); 274 AudioTestObjAddMetadataStr(Obj, "stream_period_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPeriod); 275 AudioTestObjAddMetadataStr(Obj, "stream_buffer_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesBufferSize); 276 AudioTestObjAddMetadataStr(Obj, "stream_prebuf_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPreBuffering); 277 /* Note: This mostly is provided by backend (e.g. PulseAudio / ALSA / ++) and 278 * has nothing to do with the device emulation scheduling hint. */ 279 AudioTestObjAddMetadataStr(Obj, "device_scheduling_hint_ms=%RU32\n", pStream->Cfg.Device.cMsSchedulingHint); 282 if (pTstEnv) 283 { 284 AudioTestObjAddMetadataStr(Obj, "stream_to_play_bytes=%RU32\n", cbToPlayTotal); 285 AudioTestObjAddMetadataStr(Obj, "stream_period_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPeriod); 286 AudioTestObjAddMetadataStr(Obj, "stream_buffer_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesBufferSize); 287 AudioTestObjAddMetadataStr(Obj, "stream_prebuf_size_frames=%RU32\n", pStream->Cfg.Backend.cFramesPreBuffering); 288 /* Note: This mostly is provided by backend (e.g. PulseAudio / ALSA / ++) and 289 * has nothing to do with the device emulation scheduling hint. */ 290 AudioTestObjAddMetadataStr(Obj, "device_scheduling_hint_ms=%RU32\n", pStream->Cfg.Device.cMsSchedulingHint); 291 } 280 292 281 293 PAUDIOTESTDRVMIXSTREAM pMix = &pStream->Mix; … … 309 321 if (RT_SUCCESS(rc)) 310 322 { 311 /* Write stuff to disk before trying to play it. Help analysis later. */ 312 rc = AudioTestObjWrite(Obj, abBuf, cbToPlay); 323 if (pTstEnv) 324 { 325 /* Write stuff to disk before trying to play it. Help analysis later. */ 326 rc = AudioTestObjWrite(Obj, abBuf, cbToPlay); 327 } 313 328 if (RT_SUCCESS(rc)) 314 329 { … … 342 357 rc = VERR_AUDIO_STREAM_NOT_READY; 343 358 344 int rc2 = AudioTestObjClose(Obj); 345 if (RT_SUCCESS(rc)) 346 rc = rc2; 359 if (pTstEnv) 360 { 361 int rc2 = AudioTestObjClose(Obj); 362 if (RT_SUCCESS(rc)) 363 rc = rc2; 364 } 347 365 348 366 if (RT_FAILURE(rc)) -
trunk/src/VBox/ValidationKit/utils/audio/vkatInternal.h
r90117 r90723 463 463 int audioTestWorker(PAUDIOTESTENV pTstEnv); 464 464 465 /** @todo Test tone handling */ 466 int audioTestPlayTone(PAUDIOTESTENV pTstEnv, PAUDIOTESTSTREAM pStream, PAUDIOTESTTONEPARMS pParms); 467 /** @} */ 468 465 469 /** @name Command handlers 466 470 * @{ */
Note:
See TracChangeset
for help on using the changeset viewer.