Changeset 89333 in vbox for trunk/src/VBox/Devices/Audio
- Timestamp:
- May 28, 2021 8:31:50 AM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 144682
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioMixBuffer.cpp
r89332 r89333 2339 2339 2340 2340 /** 2341 * Writes audio frames.2342 *2343 * The sample format being written must match the format of the mixing buffer.2344 *2345 * @returns VBox status code2346 * @retval VERR_BUFFER_OVERFLOW if frames which not have been processed yet2347 * have been overwritten (due to cyclic buffer).2348 * @param pMixBuf Pointer to mixing buffer to write to.2349 * @param pvBuf Pointer to audio buffer to be written.2350 * @param cbBuf Size (in bytes) of audio buffer.2351 * @param pcWritten Returns number of audio frames written. Optional.2352 */2353 int AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)2354 {2355 return AudioMixBufWriteCircEx(pMixBuf, &pMixBuf->Props, pvBuf, cbBuf, pcWritten);2356 }2357 2358 /**2359 * Writes audio frames of a specific format.2360 * This function might write less data at once than requested.2361 *2362 * @returns VBox status code2363 * @retval VERR_BUFFER_OVERFLOW no space is available for writing anymore.2364 * @param pMixBuf Pointer to mixing buffer to write to.2365 * @param pSrcProps The source format.2366 * @param pvBuf Pointer to audio buffer to be written.2367 * @param cbBuf Size (in bytes) of audio buffer.2368 * @param pcWritten Returns number of audio frames written. Optional.2369 */2370 int AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,2371 const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten)2372 {2373 /*2374 * Assert sanity.2375 */2376 AssertPtrReturn(pMixBuf, VERR_INVALID_POINTER);2377 AssertReturn(pMixBuf->uMagic == AUDIOMIXBUF_MAGIC, VERR_INVALID_HANDLE);2378 Assert(pMixBuf->cFrames);2379 AssertPtr(pMixBuf->pFrames);2380 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);2381 AssertPtrNullReturn(pcWritten, VERR_INVALID_POINTER);2382 2383 /*2384 * Make sure that we at least write a full audio frame.2385 */2386 uint32_t const cFramesInBuf = PDMAudioPropsBytesToFrames(pSrcProps, cbBuf);2387 if (cFramesInBuf > 0)2388 { /* likely */ }2389 else2390 {2391 if (pcWritten)2392 *pcWritten = 0;2393 AssertReturn(cbBuf == 0, VERR_INVALID_PARAMETER);2394 return VINF_SUCCESS;2395 }2396 2397 /*2398 * Get the conversion function matching pSrcProps, doing special2399 * optimizations for a muted buffer.2400 */2401 PFNAUDIOMIXBUFCONVFROM pfnConvFrom = NULL;2402 if (!pMixBuf->Volume.fMuted)2403 {2404 if (PDMAudioPropsAreEqual(&pMixBuf->Props, pSrcProps))2405 pfnConvFrom = pMixBuf->pfnConvFrom;2406 else2407 pfnConvFrom = audioMixBufConvFromLookup(pSrcProps);2408 AssertReturn(pfnConvFrom, VERR_NOT_SUPPORTED);2409 }2410 else2411 pfnConvFrom = &audioMixBufConvFromSilence;2412 2413 /*2414 * Is there any free space left in the buffer?2415 */2416 int rc = VINF_SUCCESS;2417 uint32_t cFramesWritten = 0;2418 uint32_t cFramesFree = pMixBuf->cFrames - pMixBuf->cUsed;2419 if (cFramesFree > 0)2420 {2421 /*2422 * There are potentially two writes we can make, one from offWrite and2423 * a 2nd one from the start of the buffer.2424 */2425 uint32_t cFramesToWrite1 = RT_MIN(pMixBuf->cFrames - pMixBuf->offWrite, cFramesFree);2426 uint32_t cFramesToWrite2 = 0;2427 if (cFramesToWrite1 >= cFramesInBuf)2428 cFramesToWrite1 = cFramesInBuf; /* The first write can hold it all. */2429 else if (cFramesFree >= cFramesInBuf)2430 cFramesToWrite2 = cFramesInBuf - cFramesToWrite1; /* If we wrap around, we can make it all fit. */2431 else if (cFramesToWrite1 < cFramesFree)2432 cFramesToWrite2 = cFramesFree - cFramesToWrite1; /* Not enough free space. Must wrap around to fill it all, though. */2433 else2434 cFramesToWrite1 = cFramesFree; /* Not enough free space, the read position is before the wraparound. */2435 Assert(cFramesToWrite1);2436 Log4Func(("cbBuf=%#x cFramesInBuf=%#x cFramesFree=%#x offWrite=%#x cFrames=%#x => %#x + %#x\n",2437 cbBuf, cFramesInBuf, cFramesFree, pMixBuf->offWrite, pMixBuf->cFrames, cFramesToWrite1, cFramesToWrite2));2438 2439 /*2440 * Set up the conversion and do the first chunk.2441 */2442 AUDMIXBUFCONVOPTS ConvOpts;2443 ConvOpts.From.Volume.fMuted = pMixBuf->Volume.fMuted;2444 ConvOpts.From.Volume.uLeft = pMixBuf->Volume.uLeft;2445 ConvOpts.From.Volume.uRight = pMixBuf->Volume.uRight;2446 ConvOpts.cFrames = cFramesToWrite1;2447 2448 uint32_t const cbToWrite1 = PDMAudioPropsFramesToBytes(pSrcProps, cFramesToWrite1);2449 cFramesWritten = pfnConvFrom(&pMixBuf->pFrames[pMixBuf->offWrite],2450 pvBuf, PDMAudioPropsFramesToBytes(pSrcProps, cFramesToWrite1), &ConvOpts);2451 Assert(cFramesWritten == cFramesToWrite1);2452 2453 /*2454 * Any 2nd buffer?2455 */2456 if (cFramesToWrite2 > 0 && cFramesWritten == cFramesToWrite1)2457 {2458 ConvOpts.cFrames = cFramesToWrite2;2459 uint32_t const cbToWrite2 = PDMAudioPropsFramesToBytes(pSrcProps, cFramesToWrite2);2460 cFramesWritten += pfnConvFrom(&pMixBuf->pFrames[0], (uint8_t const *)pvBuf + cbToWrite1, cbToWrite2, &ConvOpts);2461 Assert(cFramesWritten == cFramesToWrite2 + cFramesToWrite1);2462 }2463 2464 /*2465 * Advance the buffer position.2466 */2467 pMixBuf->cUsed += cFramesWritten;2468 Assert(pMixBuf->cUsed <= pMixBuf->cFrames);2469 2470 pMixBuf->offWrite = (pMixBuf->offWrite + cFramesWritten) % pMixBuf->cFrames;2471 Assert(pMixBuf->offWrite < pMixBuf->cFrames);2472 2473 /*2474 * Debug stuff.2475 */2476 #ifdef AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA2477 RTFILE fh;2478 RTFileOpen(&fh, AUDIOMIXBUF_DEBUG_DUMP_PCM_DATA_PATH "mixbuf_writecirc_ex.pcm",2479 RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND | RTFILE_O_WRITE | RTFILE_O_DENY_NONE);2480 RTFileWrite(fh, pvBuf, PDMAudioPropsFramesToBytes(pSrcProps, cFramesWritten), NULL);2481 RTFileClose(fh);2482 #endif2483 }2484 else2485 rc = VERR_BUFFER_OVERFLOW;2486 2487 #ifdef DEBUG2488 audioMixBufDbgPrintInternal(pMixBuf, __FUNCTION__);2489 audioMixBufDbgValidate(pMixBuf);2490 #endif2491 2492 if (pcWritten)2493 *pcWritten = cFramesWritten;2494 2495 #ifdef AUDMIXBUF_LOG_ENABLED2496 char szTmp[PDMAUDIOPROPSTOSTRING_MAX];2497 #endif2498 AUDMIXBUF_LOG(("%s: pSrcProps=%s, cbBuf=%RU32 (%RU32 frames), cFramesWritten=%RU32, rc=%Rrc\n", pMixBuf->pszName,2499 PDMAudioPropsToString(pSrcProps, szTmp, sizeof(szTmp)), cbBuf, AUDIOMIXBUF_B2F(pMixBuf, cbBuf), cFramesWritten, rc));2500 return rc;2501 }2502 2503 /**2504 2341 * Returns the current write position of a mixing buffer. 2505 2342 * -
trunk/src/VBox/Devices/Audio/AudioMixBuffer.h
r89332 r89333 292 292 uint32_t AudioMixBufSize(PAUDIOMIXBUF pMixBuf); 293 293 uint32_t AudioMixBufSizeBytes(PAUDIOMIXBUF pMixBuf); 294 int AudioMixBufWriteCirc(PAUDIOMIXBUF pMixBuf, const void *pvBuf, uint32_t cbBuf, uint32_t *pcWritten);295 int AudioMixBufWriteCircEx(PAUDIOMIXBUF pMixBuf, PCPDMAUDIOPCMPROPS pSrcProps,296 const void *pvBuf,uint32_t cbBuf, uint32_t *pcWritten);297 294 uint32_t AudioMixBufWritePos(PAUDIOMIXBUF pMixBuf); 298 295 -
trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
r89332 r89333 272 272 for (uint32_t i = 0; i < cToWrite; i++) 273 273 { 274 RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &aFrames16, sizeof(aFrames16), &cFramesWritten));274 AudioMixBufWrite(&mb, &WrState, &aFrames16[0], sizeof(aFrames16), 0 /*offDstFrame*/, 1, &cFramesWritten); 275 275 RTTESTI_CHECK(cFramesWritten == 1); 276 AudioMixBufCommit(&mb, cFramesWritten); 276 277 } 277 278 RTTESTI_CHECK(!AudioMixBufIsEmpty(&mb)); … … 280 281 RTTESTI_CHECK(AudioMixBufUsed(&mb) == cToWrite + cFramesWrittenAbs /* + last absolute write */); 281 282 282 RTTESTI_CHECK_RC_OK(AudioMixBufWriteCirc(&mb, &aFrames16, sizeof(aFrames16), &cFramesWritten));283 AudioMixBufWrite(&mb, &WrState, &aFrames16[0], sizeof(aFrames16), 0 /*offDstFrame*/, 1, &cFramesWritten); 283 284 RTTESTI_CHECK(cFramesWritten == 1); 285 AudioMixBufCommit(&mb, cFramesWritten); 284 286 RTTESTI_CHECK(AudioMixBufFree(&mb) == 0); 285 287 RTTESTI_CHECK(AudioMixBufFreeBytes(&mb) == AUDIOMIXBUF_F2B(&mb, 0U)); … … 572 574 RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInit(&MixBuf, "NewPeekMixBuf", &CfgSrc, cFrames)); 573 575 576 /* Write state (source). */ 577 AUDIOMIXBUFWRITESTATE WriteState; 578 RTTESTI_CHECK_RC_OK_RETV(AudioMixBufInitWriteState(&MixBuf, &WriteState, &CfgSrc)); 579 574 580 /* Peek state (destination) is uToHz 2ch S16 */ 575 581 PDMAUDIOPCMPROPS const CfgDst = PDMAUDIOPCMPROPS_INITIALIZER(2 /*cbSample*/, true /*fSigned*/, 2 /*ch*/, uToHz, false /*fSwap*/); … … 607 613 608 614 uint32_t cSrcFramesWritten = UINT32_MAX / 2; 609 RTTESTI_CHECK_RC_OK_BREAK(AudioMixBufWriteCirc(&MixBuf, &aSrcFrames, cSrcFrames * sizeof(aSrcFrames[0]), &cSrcFramesWritten)); 615 AudioMixBufWrite(&MixBuf, &WriteState, &aSrcFrames[0], cSrcFrames * sizeof(aSrcFrames[0]), 616 0 /*offDstFrame*/, cSrcFrames, &cSrcFramesWritten); 610 617 RTTESTI_CHECK_MSG_BREAK(cSrcFrames == cSrcFramesWritten, 611 618 ("cSrcFrames=%RU32 vs cSrcFramesWritten=%RU32 cLiveFrames=%RU32\n", 612 619 cSrcFrames, cSrcFramesWritten, AudioMixBufLive(&MixBuf))); 620 AudioMixBufCommit(&MixBuf, cSrcFrames); 613 621 614 622 /*
Note:
See TracChangeset
for help on using the changeset viewer.