Changeset 88028 in vbox
- Timestamp:
- Mar 8, 2021 7:31:22 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 143156
- Location:
- trunk
- Files:
-
- 23 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/pdmaudioinline.h
r88027 r88028 1 1 /* $Id$ */ 2 2 /** @file 3 * Intermedia audio driver, common routines.4 * 5 * Th ese are also used in the drivers which are bound to Main, e.g. the VRDE6 * or the video audio recording drivers.3 * PDM - Audio Helpers, Inlined Code. (DEV,++) 4 * 5 * This is all inlined because it's too tedious to create a couple libraries to 6 * contain it all (same bad excuse as for intnetinline.h & pdmnetinline.h). 7 7 */ 8 8 … … 17 17 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 18 18 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 19 */ 19 * 20 * The contents of this file may alternatively be used under the terms 21 * of the Common Development and Distribution License Version 1.0 22 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the 23 * VirtualBox OSE distribution, in which case the provisions of the 24 * CDDL are applicable instead of those of the GPL. 25 * 26 * You may elect to license modified versions of this file under the 27 * terms and conditions of either the GPL or the CDDL or both. 28 */ 29 30 #ifndef VBOX_INCLUDED_vmm_pdmaudioinline_h 31 #define VBOX_INCLUDED_vmm_pdmaudioinline_h 32 #ifndef RT_WITHOUT_PRAGMA_ONCE 33 # pragma once 34 #endif 20 35 21 36 … … 23 38 * Header Files * 24 39 *********************************************************************************************************************************/ 25 #include <iprt/alloc.h> 40 #include <VBox/err.h> 41 #include <VBox/log.h> 42 #include <VBox/vmm/pdmaudioifs.h> 43 44 #include <iprt/asm.h> 26 45 #include <iprt/asm-math.h> 27 46 #include <iprt/assert.h> 28 #include <iprt/dir.h> 29 #include <iprt/file.h> 47 #include <iprt/mem.h> 30 48 #include <iprt/string.h> 31 #include <iprt/uuid.h> 32 33 #define LOG_GROUP LOG_GROUP_DRV_AUDIO 34 #include <VBox/log.h> 35 36 #include <VBox/err.h> 37 #include <VBox/vmm/pdmdev.h> 38 #include <VBox/vmm/pdm.h> 39 #include <VBox/vmm/mm.h> 40 41 #include <ctype.h> 42 #include <stdlib.h> 43 44 #include "DrvAudio.h" 45 #include "AudioMixBuffer.h" 46 47 48 /********************************************************************************************************************************* 49 * Structures and Typedefs * 50 *********************************************************************************************************************************/ 51 /** 52 * Structure for building up a .WAV file header. 53 */ 54 typedef struct AUDIOWAVFILEHDR 55 { 56 uint32_t u32RIFF; 57 uint32_t u32Size; 58 uint32_t u32WAVE; 59 60 uint32_t u32Fmt; 61 uint32_t u32Size1; 62 uint16_t u16AudioFormat; 63 uint16_t u16NumChannels; 64 uint32_t u32SampleRate; 65 uint32_t u32ByteRate; 66 uint16_t u16BlockAlign; 67 uint16_t u16BitsPerSample; 68 69 uint32_t u32ID2; 70 uint32_t u32Size2; 71 } AUDIOWAVFILEHDR, *PAUDIOWAVFILEHDR; 72 AssertCompileSize(AUDIOWAVFILEHDR, 11*4); 73 74 /** 75 * Structure for keeeping the internal .WAV file data 76 */ 77 typedef struct AUDIOWAVFILEDATA 78 { 79 /** The file header/footer. */ 80 AUDIOWAVFILEHDR Hdr; 81 } AUDIOWAVFILEDATA, *PAUDIOWAVFILEDATA; 82 83 84 85 86 /** 87 * Retrieves the matching PDMAUDIOFMT for the given bits + signing flag. 88 * 89 * @return Matching PDMAUDIOFMT value. 90 * @retval PDMAUDIOFMT_INVALID if unsupported @a cBits value. 91 * 92 * @param cBits The number of bits in the audio format. 93 * @param fSigned Whether the audio format is signed @c true or not. 94 */ 95 PDMAUDIOFMT DrvAudioAudFmtBitsToFormat(uint8_t cBits, bool fSigned) 96 { 97 if (fSigned) 98 { 99 switch (cBits) 100 { 101 case 8: return PDMAUDIOFMT_S8; 102 case 16: return PDMAUDIOFMT_S16; 103 case 32: return PDMAUDIOFMT_S32; 104 default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID); 105 } 106 } 107 else 108 { 109 switch (cBits) 110 { 111 case 8: return PDMAUDIOFMT_U8; 112 case 16: return PDMAUDIOFMT_U16; 113 case 32: return PDMAUDIOFMT_U32; 114 default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID); 115 } 116 } 117 } 118 119 /** 120 * Returns an unique file name for this given audio connector instance. 121 * 122 * @return Allocated file name. Must be free'd using RTStrFree(). 123 * @param uInstance Driver / device instance. 124 * @param pszPath Path name of the file to delete. The path must exist. 125 * @param pszSuffix File name suffix to use. 126 */ 127 char *DrvAudioDbgGetFileNameA(uint8_t uInstance, const char *pszPath, const char *pszSuffix) 128 { 129 char szFileName[64]; 130 RTStrPrintf(szFileName, sizeof(szFileName), "drvAudio%RU8-%s", uInstance, pszSuffix); 131 132 char szFilePath[RTPATH_MAX]; 133 int rc2 = RTStrCopy(szFilePath, sizeof(szFilePath), pszPath); 134 AssertRC(rc2); 135 rc2 = RTPathAppend(szFilePath, sizeof(szFilePath), szFileName); 136 AssertRC(rc2); 137 138 return RTStrDup(szFilePath); 139 } 140 141 /** 142 * Allocates an audio device. 143 * 144 * @returns Newly allocated audio device, or NULL if failed. 145 * @param cbData How much additional data (in bytes) should be allocated to provide 146 * a (backend) specific area to store additional data. 147 * Optional, can be 0. 148 */ 149 PPDMAUDIODEVICE DrvAudioHlpDeviceAlloc(size_t cbData) 150 { 151 PPDMAUDIODEVICE pDev = (PPDMAUDIODEVICE)RTMemAllocZ(sizeof(PDMAUDIODEVICE)); 152 if (!pDev) 153 return NULL; 154 155 if (cbData) 156 { 157 pDev->pvData = RTMemAllocZ(cbData); 158 if (!pDev->pvData) 159 { 160 RTMemFree(pDev); 161 return NULL; 162 } 163 } 164 165 pDev->cbData = cbData; 166 167 pDev->cMaxInputChannels = 0; 168 pDev->cMaxOutputChannels = 0; 169 170 return pDev; 171 } 172 173 /** 174 * Frees an audio device. 175 * 176 * @param pDev Device to free. 177 */ 178 void DrvAudioHlpDeviceFree(PPDMAUDIODEVICE pDev) 179 { 180 if (!pDev) 181 return; 182 183 Assert(pDev->cRefCount == 0); 184 185 if (pDev->pvData) 186 { 187 Assert(pDev->cbData); 188 189 RTMemFree(pDev->pvData); 190 pDev->pvData = NULL; 191 } 192 193 RTMemFree(pDev); 194 pDev = NULL; 195 } 196 197 /** 198 * Duplicates an audio device entry. 199 * 200 * @returns Duplicated audio device entry on success, or NULL on failure. 201 * @param pDev Audio device entry to duplicate. 202 * @param fCopyUserData Whether to also copy the user data portion or not. 203 */ 204 PPDMAUDIODEVICE DrvAudioHlpDeviceDup(const PPDMAUDIODEVICE pDev, bool fCopyUserData) 205 { 206 AssertPtrReturn(pDev, NULL); 207 208 PPDMAUDIODEVICE pDevDup = DrvAudioHlpDeviceAlloc(fCopyUserData ? pDev->cbData : 0); 209 if (pDevDup) 210 { 211 memcpy(pDevDup, pDev, sizeof(PDMAUDIODEVICE)); 212 213 if ( fCopyUserData 214 && pDevDup->cbData) 215 { 216 memcpy(pDevDup->pvData, pDev->pvData, pDevDup->cbData); 217 } 218 else 219 { 220 pDevDup->cbData = 0; 221 pDevDup->pvData = NULL; 222 } 223 } 224 225 return pDevDup; 226 } 227 228 /** 229 * Initializes an audio device enumeration structure. 230 * 231 * @returns IPRT status code. 232 * @param pDevEnm Device enumeration to initialize. 233 */ 234 int DrvAudioHlpDeviceEnumInit(PPDMAUDIODEVICEENUM pDevEnm) 235 { 236 AssertPtrReturn(pDevEnm, VERR_INVALID_POINTER); 237 238 RTListInit(&pDevEnm->lstDevices); 239 pDevEnm->cDevices = 0; 240 241 return VINF_SUCCESS; 242 } 243 244 /** 245 * Frees audio device enumeration data. 246 * 247 * @param pDevEnm Device enumeration to destroy. 248 */ 249 void DrvAudioHlpDeviceEnumFree(PPDMAUDIODEVICEENUM pDevEnm) 250 { 251 if (!pDevEnm) 252 return; 253 254 PPDMAUDIODEVICE pDev, pDevNext; 255 RTListForEachSafe(&pDevEnm->lstDevices, pDev, pDevNext, PDMAUDIODEVICE, Node) 256 { 257 RTListNodeRemove(&pDev->Node); 258 259 DrvAudioHlpDeviceFree(pDev); 260 261 pDevEnm->cDevices--; 262 } 263 264 /* Sanity. */ 265 Assert(RTListIsEmpty(&pDevEnm->lstDevices)); 266 Assert(pDevEnm->cDevices == 0); 267 } 268 269 /** 270 * Adds an audio device to a device enumeration. 271 * 272 * @return IPRT status code. 273 * @param pDevEnm Device enumeration to add device to. 274 * @param pDev Device to add. The pointer will be owned by the device enumeration then. 275 */ 276 int DrvAudioHlpDeviceEnumAdd(PPDMAUDIODEVICEENUM pDevEnm, PPDMAUDIODEVICE pDev) 277 { 278 AssertPtrReturn(pDevEnm, VERR_INVALID_POINTER); 279 AssertPtrReturn(pDev, VERR_INVALID_POINTER); 280 281 RTListAppend(&pDevEnm->lstDevices, &pDev->Node); 282 pDevEnm->cDevices++; 283 284 return VINF_SUCCESS; 285 } 286 287 /** 288 * Duplicates a device enumeration. 289 * 290 * @returns Duplicated device enumeration, or NULL on failure. 291 * Must be free'd with DrvAudioHlpDeviceEnumFree(). 292 * @param pDevEnm Device enumeration to duplicate. 293 */ 294 PPDMAUDIODEVICEENUM DrvAudioHlpDeviceEnumDup(const PPDMAUDIODEVICEENUM pDevEnm) 295 { 296 AssertPtrReturn(pDevEnm, NULL); 297 298 PPDMAUDIODEVICEENUM pDevEnmDup = (PPDMAUDIODEVICEENUM)RTMemAlloc(sizeof(PDMAUDIODEVICEENUM)); 299 if (!pDevEnmDup) 300 return NULL; 301 302 int rc2 = DrvAudioHlpDeviceEnumInit(pDevEnmDup); 303 AssertRC(rc2); 304 305 PPDMAUDIODEVICE pDev; 306 RTListForEach(&pDevEnm->lstDevices, pDev, PDMAUDIODEVICE, Node) 307 { 308 PPDMAUDIODEVICE pDevDup = DrvAudioHlpDeviceDup(pDev, true /* fCopyUserData */); 309 if (!pDevDup) 310 { 311 rc2 = VERR_NO_MEMORY; 312 break; 313 } 314 315 rc2 = DrvAudioHlpDeviceEnumAdd(pDevEnmDup, pDevDup); 316 if (RT_FAILURE(rc2)) 317 { 318 DrvAudioHlpDeviceFree(pDevDup); 319 break; 320 } 321 } 322 323 if (RT_FAILURE(rc2)) 324 { 325 DrvAudioHlpDeviceEnumFree(pDevEnmDup); 326 pDevEnmDup = NULL; 327 } 328 329 return pDevEnmDup; 330 } 331 332 /** 333 * Copies device enumeration entries from the source to the destination enumeration. 334 * 335 * @returns IPRT status code. 336 * @param pDstDevEnm Destination enumeration to store enumeration entries into. 337 * @param pSrcDevEnm Source enumeration to use. 338 * @param enmUsage Which entries to copy. Specify PDMAUDIODIR_DUPLEX to copy all entries. 339 * @param fCopyUserData Whether to also copy the user data portion or not. 340 */ 341 int DrvAudioHlpDeviceEnumCopyEx(PPDMAUDIODEVICEENUM pDstDevEnm, const PPDMAUDIODEVICEENUM pSrcDevEnm, 342 PDMAUDIODIR enmUsage, bool fCopyUserData) 343 { 344 AssertPtrReturn(pDstDevEnm, VERR_INVALID_POINTER); 345 AssertPtrReturn(pSrcDevEnm, VERR_INVALID_POINTER); 346 347 int rc = VINF_SUCCESS; 348 349 PPDMAUDIODEVICE pSrcDev; 350 RTListForEach(&pSrcDevEnm->lstDevices, pSrcDev, PDMAUDIODEVICE, Node) 351 { 352 if ( enmUsage != PDMAUDIODIR_DUPLEX 353 && enmUsage != pSrcDev->enmUsage) 354 { 355 continue; 356 } 357 358 PPDMAUDIODEVICE pDstDev = DrvAudioHlpDeviceDup(pSrcDev, fCopyUserData); 359 if (!pDstDev) 360 { 361 rc = VERR_NO_MEMORY; 362 break; 363 } 364 365 rc = DrvAudioHlpDeviceEnumAdd(pDstDevEnm, pDstDev); 366 if (RT_FAILURE(rc)) 367 break; 368 } 369 370 return rc; 371 } 372 373 /** 374 * Copies all device enumeration entries from the source to the destination enumeration. 375 * 376 * Note: Does *not* copy the user-specific data assigned to a device enumeration entry. 377 * To do so, use DrvAudioHlpDeviceEnumCopyEx(). 378 * 379 * @returns IPRT status code. 380 * @param pDstDevEnm Destination enumeration to store enumeration entries into. 381 * @param pSrcDevEnm Source enumeration to use. 382 */ 383 int DrvAudioHlpDeviceEnumCopy(PPDMAUDIODEVICEENUM pDstDevEnm, const PPDMAUDIODEVICEENUM pSrcDevEnm) 384 { 385 return DrvAudioHlpDeviceEnumCopyEx(pDstDevEnm, pSrcDevEnm, PDMAUDIODIR_DUPLEX, false /* fCopyUserData */); 386 } 387 388 /** 389 * Returns the default device of a given device enumeration. 390 * This assumes that only one default device per usage is set. 391 * 392 * @returns Default device if found, or NULL if none found. 393 * @param pDevEnm Device enumeration to get default device for. 394 * @param enmUsage Usage to get default device for. 395 */ 396 PPDMAUDIODEVICE DrvAudioHlpDeviceEnumGetDefaultDevice(const PPDMAUDIODEVICEENUM pDevEnm, PDMAUDIODIR enmUsage) 397 { 398 AssertPtrReturn(pDevEnm, NULL); 399 400 PPDMAUDIODEVICE pDev; 401 RTListForEach(&pDevEnm->lstDevices, pDev, PDMAUDIODEVICE, Node) 402 { 403 if (enmUsage != PDMAUDIODIR_DUPLEX) 404 { 405 if (enmUsage != pDev->enmUsage) /* Wrong usage? Skip. */ 406 continue; 407 } 408 409 if (pDev->fFlags & PDMAUDIODEV_FLAGS_DEFAULT) 410 return pDev; 411 } 412 413 return NULL; 414 } 415 416 /** 417 * Returns the number of enumerated devices of a given device enumeration. 418 * 419 * @returns Number of devices if found, or 0 if none found. 420 * @param pDevEnm Device enumeration to get default device for. 421 * @param enmUsage Usage to get default device for. 422 */ 423 uint16_t DrvAudioHlpDeviceEnumGetDeviceCount(const PPDMAUDIODEVICEENUM pDevEnm, PDMAUDIODIR enmUsage) 424 { 425 AssertPtrReturn(pDevEnm, 0); 426 427 if (enmUsage == PDMAUDIODIR_DUPLEX) 428 return pDevEnm->cDevices; 429 430 uint32_t cDevs = 0; 431 432 PPDMAUDIODEVICE pDev; 433 RTListForEach(&pDevEnm->lstDevices, pDev, PDMAUDIODEVICE, Node) 434 { 435 if (enmUsage == pDev->enmUsage) 436 cDevs++; 437 } 438 439 return cDevs; 440 } 441 442 /** 443 * Logs an audio device enumeration. 444 * 445 * @param pszDesc Logging description. 446 * @param pDevEnm Device enumeration to log. 447 */ 448 void DrvAudioHlpDeviceEnumPrint(const char *pszDesc, const PPDMAUDIODEVICEENUM pDevEnm) 449 { 450 AssertPtrReturnVoid(pszDesc); 451 AssertPtrReturnVoid(pDevEnm); 452 453 LogFunc(("%s: %RU16 devices\n", pszDesc, pDevEnm->cDevices)); 454 455 PPDMAUDIODEVICE pDev; 456 RTListForEach(&pDevEnm->lstDevices, pDev, PDMAUDIODEVICE, Node) 457 { 458 char *pszFlags = DrvAudioHlpAudDevFlagsToStrA(pDev->fFlags); 459 460 LogFunc(("Device '%s':\n", pDev->szName)); 461 LogFunc(("\tUsage = %s\n", PDMAudioDirGetName(pDev->enmUsage))); 462 LogFunc(("\tFlags = %s\n", pszFlags ? pszFlags : "<NONE>")); 463 LogFunc(("\tInput channels = %RU8\n", pDev->cMaxInputChannels)); 464 LogFunc(("\tOutput channels = %RU8\n", pDev->cMaxOutputChannels)); 465 LogFunc(("\tData = %p (%zu bytes)\n", pDev->pvData, pDev->cbData)); 466 467 if (pszFlags) 468 RTStrFree(pszFlags); 469 } 470 } 49 50 51 /* Fix later: */ 52 DECLINLINE(bool) PDMAudioPropsAreValid(PCPDMAUDIOPCMPROPS pProps); 53 DECLINLINE(bool) PDMAudioPropsAreEqual(PCPDMAUDIOPCMPROPS pProps1, PCPDMAUDIOPCMPROPS pProps2); 54 55 471 56 472 57 /** 473 58 * Gets the name of an audio direction enum value. 474 59 * 475 * @returns Pointer to read-only name string on success, " Unknown" if60 * @returns Pointer to read-only name string on success, "bad" if 476 61 * passed an invalid enum value. 477 62 * @param enmDir The audio direction value to name. 478 63 */ 479 const char *PDMAudioDirGetName(PDMAUDIODIR enmDir)64 DECLINLINE(const char *) PDMAudioDirGetName(PDMAUDIODIR enmDir) 480 65 { 481 66 switch (enmDir) … … 491 76 break; 492 77 } 493 AssertMsgFailedReturn(("Invalid audio direction %d\n", enmDir), " Unknown");494 } 495 496 /** 497 * Converts an audio mixer control to a string.498 * 499 * @returns Stringified audio mixer control or "Unknown", if not found.500 * @param enmMixerCtl Audio mixer control to convert.501 */ 502 const char *PDMAudioMixerCtlGetName(PDMAUDIOMIXERCTL enmMixerCtl)78 AssertMsgFailedReturn(("Invalid audio direction %d\n", enmDir), "bad"); 79 } 80 81 /** 82 * Gets the name of an audio mixer control enum value. 83 * 84 * @returns Pointer to read-only name, "bad" if invalid input. 85 * @param enmMixerCtl The audio mixer control value. 86 */ 87 DECLINLINE(const char *) PDMAudioMixerCtlGetName(PDMAUDIOMIXERCTL enmMixerCtl) 503 88 { 504 89 switch (enmMixerCtl) 505 90 { 91 case PDMAUDIOMIXERCTL_UNKNOWN: return "Unknown"; 506 92 case PDMAUDIOMIXERCTL_VOLUME_MASTER: return "Master Volume"; 507 93 case PDMAUDIOMIXERCTL_FRONT: return "Front"; … … 510 96 case PDMAUDIOMIXERCTL_LINE_IN: return "Line-In"; 511 97 case PDMAUDIOMIXERCTL_MIC_IN: return "Microphone-In"; 512 default: break; 513 } 514 515 AssertMsgFailed(("Invalid mixer control %ld\n", enmMixerCtl)); 516 return "Unknown"; 517 } 518 519 /** 520 * Converts an audio device flags to a string. 521 * 522 * @returns Stringified audio flags. Must be free'd with RTStrFree(). 523 * NULL if no flags set. 524 * @param fFlags Audio flags (PDMAUDIODEV_FLAGS_XXX) to convert. 525 */ 526 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags) 527 { 528 #define APPEND_FLAG_TO_STR(_aFlag) \ 529 if (fFlags & PDMAUDIODEV_FLAGS_##_aFlag) \ 530 { \ 531 if (pszFlags) \ 532 { \ 533 rc2 = RTStrAAppend(&pszFlags, " "); \ 534 if (RT_FAILURE(rc2)) \ 535 break; \ 536 } \ 537 \ 538 rc2 = RTStrAAppend(&pszFlags, #_aFlag); \ 539 if (RT_FAILURE(rc2)) \ 540 break; \ 541 } \ 542 543 char *pszFlags = NULL; 544 int rc2 = VINF_SUCCESS; 545 546 do 547 { 548 APPEND_FLAG_TO_STR(DEFAULT); 549 APPEND_FLAG_TO_STR(HOTPLUG); 550 APPEND_FLAG_TO_STR(BUGGY); 551 APPEND_FLAG_TO_STR(IGNORE); 552 APPEND_FLAG_TO_STR(LOCKED); 553 APPEND_FLAG_TO_STR(DEAD); 554 555 } while (0); 556 557 if (!pszFlags) 558 rc2 = RTStrAAppend(&pszFlags, "NONE"); 559 560 if ( RT_FAILURE(rc2) 561 && pszFlags) 562 { 563 RTStrFree(pszFlags); 564 pszFlags = NULL; 565 } 566 567 #undef APPEND_FLAG_TO_STR 568 569 return pszFlags; 570 } 571 572 /** 573 * Converts a playback destination enumeration to a string. 574 * 575 * @returns Stringified playback destination, or "Unknown", if not found. 576 * @param enmPlaybackDst Playback destination to convert. 577 */ 578 const char *PDMAudioPlaybackDstGetName(const PDMAUDIOPLAYBACKDST enmPlaybackDst) 98 /* no default */ 99 case PDMAUDIOMIXERCTL_INVALID: 100 case PDMAUDIOMIXERCTL_32BIT_HACK: 101 break; 102 } 103 AssertMsgFailedReturn(("Invalid mixer control %ld\n", enmMixerCtl), "bad"); 104 } 105 106 /** 107 * Gets the name of a playback destination enum value. 108 * 109 * @returns Pointer to read-only name, "bad" if invalid input. 110 * @param enmPlaybackDst The playback destination value. 111 */ 112 DECLINLINE(const char *) PDMAudioPlaybackDstGetName(PDMAUDIOPLAYBACKDST enmPlaybackDst) 579 113 { 580 114 switch (enmPlaybackDst) … … 584 118 case PDMAUDIOPLAYBACKDST_CENTER_LFE: return "Center / LFE"; 585 119 case PDMAUDIOPLAYBACKDST_REAR: return "Rear"; 586 default: 120 /* no default */ 121 case PDMAUDIOPLAYBACKDST_INVALID: 122 case PDMAUDIOPLAYBACKDST_32BIT_HACK: 587 123 break; 588 124 } 589 590 AssertMsgFailed(("Invalid playback destination %ld\n", enmPlaybackDst)); 591 return "Unknown"; 592 } 593 594 /** 595 * Converts a recording source enumeration to a string. 596 * 597 * @returns Stringified recording source, or "Unknown", if not found. 598 * @param enmRecSrc Recording source to convert. 599 */ 600 const char *PDMAudioRecSrcGetName(const PDMAUDIORECSRC enmRecSrc) 125 AssertMsgFailedReturn(("Invalid playback destination %ld\n", enmPlaybackDst), "bad"); 126 } 127 128 /** 129 * Gets the name of a recording source enum value. 130 * 131 * @returns Pointer to read-only name, "bad" if invalid input. 132 * @param enmRecSrc The recording source value. 133 */ 134 DECLINLINE(const char *) PDMAudioRecSrcGetName(PDMAUDIORECSRC enmRecSrc) 601 135 { 602 136 switch (enmRecSrc) … … 609 143 case PDMAUDIORECSRC_LINE: return "Line In"; 610 144 case PDMAUDIORECSRC_PHONE: return "Phone"; 611 default: 145 /* no default */ 146 case PDMAUDIORECSRC_32BIT_HACK: 612 147 break; 613 148 } 614 615 AssertMsgFailed(("Invalid recording source %ld\n", enmRecSrc)); 616 return "Unknown"; 149 AssertMsgFailedReturn(("Invalid recording source %ld\n", enmRecSrc), "bad"); 617 150 } 618 151 … … 623 156 * @param enmFmt The audio format. 624 157 */ 625 boolPDMAudioFormatIsSigned(PDMAUDIOFMT enmFmt)158 DECLINLINE(bool) PDMAudioFormatIsSigned(PDMAUDIOFMT enmFmt) 626 159 { 627 160 switch (enmFmt) … … 651 184 * @param enmFmt The audio format. 652 185 */ 653 uint8_tPDMAudioFormatGetBits(PDMAUDIOFMT enmFmt)186 DECLINLINE(uint8_t) PDMAudioFormatGetBits(PDMAUDIOFMT enmFmt) 654 187 { 655 188 switch (enmFmt) … … 678 211 * Gets the name of an audio format enum value. 679 212 * 680 * @returns Pointer to read-only name on success, returns " Unknown" on if213 * @returns Pointer to read-only name on success, returns "bad" on if 681 214 * invalid enum value. 682 215 * @param enmFmt The audio format to name. 683 216 */ 684 const char *PDMAudioFormatGetName(PDMAUDIOFMT enmFmt)217 DECLINLINE(const char *) PDMAudioFormatGetName(PDMAUDIOFMT enmFmt) 685 218 { 686 219 switch (enmFmt) … … 697 230 break; 698 231 } 699 AssertMsgFailedReturn(("Bogus audio format %d\n", enmFmt), "Unknown"); 700 } 701 702 /** 703 * Converts a given string to an audio format. 704 * 705 * @returns Audio format for the given string, or PDMAUDIOFMT_INVALID if not found. 706 * @param pszFmt String to convert to an audio format. 707 */ 708 PDMAUDIOFMT DrvAudioHlpStrToAudFmt(const char *pszFmt) 709 { 710 AssertPtrReturn(pszFmt, PDMAUDIOFMT_INVALID); 711 712 if (!RTStrICmp(pszFmt, "u8")) 713 return PDMAUDIOFMT_U8; 714 if (!RTStrICmp(pszFmt, "u16")) 715 return PDMAUDIOFMT_U16; 716 if (!RTStrICmp(pszFmt, "u32")) 717 return PDMAUDIOFMT_U32; 718 if (!RTStrICmp(pszFmt, "s8")) 719 return PDMAUDIOFMT_S8; 720 if (!RTStrICmp(pszFmt, "s16")) 721 return PDMAUDIOFMT_S16; 722 if (!RTStrICmp(pszFmt, "s32")) 723 return PDMAUDIOFMT_S32; 724 725 AssertMsgFailed(("Invalid audio format '%s'\n", pszFmt)); 726 return PDMAUDIOFMT_INVALID; 727 } 728 729 #if 0 /* unused */ 730 /** 731 * Initializes a stream configuration with default values. 732 * 733 * @param pCfg The stream configuration structure to initialize. 734 */ 735 void PDMAudioStrmCfgInit(PPDMAUDIOSTREAMCFG pCfg) 736 { 737 AssertPtrReturnVoid(pCfg); 738 739 RT_ZERO(*pCfg); 740 741 pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */ 742 } 743 #endif 232 AssertMsgFailedReturn(("Bogus audio format %d\n", enmFmt), "bad"); 233 } 744 234 745 235 /** … … 750 240 * @param pProps The PCM properties to use. 751 241 */ 752 intPDMAudioStrmCfgInitWithProps(PPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps)242 DECLINLINE(int) PDMAudioStrmCfgInitWithProps(PPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps) 753 243 { 754 244 AssertPtrReturn(pProps, VERR_INVALID_POINTER); … … 761 251 762 252 return VINF_SUCCESS; 763 }764 765 /**766 * Checks whether a given stream configuration is valid or not.767 *768 * @note See notes on DrvAudioHlpPcmPropsAreValid().769 *770 * Returns @c true if configuration is valid, @c false if not.771 * @param pCfg Stream configuration to check.772 */773 bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg)774 {775 AssertPtrReturn(pCfg, false);776 777 bool fValid = ( pCfg->enmDir == PDMAUDIODIR_IN778 || pCfg->enmDir == PDMAUDIODIR_OUT);779 780 fValid &= ( pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED781 || pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);782 783 if (fValid)784 fValid = DrvAudioHlpPcmPropsAreValid(&pCfg->Props);785 786 return fValid;787 253 } 788 254 … … 794 260 * @param pProps The PCM properties to match with. 795 261 */ 796 boolPDMAudioStrmCfgMatchesProps(PCPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps)262 DECLINLINE(bool) PDMAudioStrmCfgMatchesProps(PCPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps) 797 263 { 798 264 AssertPtrReturn(pCfg, false); … … 805 271 * @param pCfg The stream configuration to free. 806 272 */ 807 voidPDMAudioStrmCfgFree(PPDMAUDIOSTREAMCFG pCfg)273 DECLINLINE(void) PDMAudioStrmCfgFree(PPDMAUDIOSTREAMCFG pCfg) 808 274 { 809 275 if (pCfg) 810 {811 276 RTMemFree(pCfg); 812 pCfg = NULL; 813 } 277 } 278 279 /** 280 * Checks whether the given stream configuration is valid or not. 281 * 282 * @returns true/false accordingly. 283 * @param pCfg Stream configuration to check. 284 * 285 * @remarks This just performs a generic check of value ranges. Further, it 286 * will assert if the input is invalid. 287 * 288 * @sa PDMAudioPropsAreValid 289 */ 290 DECLINLINE(bool) PDMAudioStrmCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg) 291 { 292 AssertPtrReturn(pCfg, false); 293 AssertMsgReturn(pCfg->enmDir >= PDMAUDIODIR_UNKNOWN && pCfg->enmDir <= PDMAUDIODIR_DUPLEX, 294 ("%d\n", pCfg->enmDir), false); 295 AssertMsgReturn(pCfg->enmLayout >= PDMAUDIOSTREAMLAYOUT_UNKNOWN && pCfg->enmLayout <= PDMAUDIOSTREAMLAYOUT_RAW, 296 ("%d\n", pCfg->enmLayout), false); 297 return PDMAudioPropsAreValid(&pCfg->Props); 814 298 } 815 299 … … 821 305 * @param pSrcCfg The source stream configuration. 822 306 */ 823 intPDMAudioStrmCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg)307 DECLINLINE(int) PDMAudioStrmCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg) 824 308 { 825 309 AssertPtrReturn(pDstCfg, VERR_INVALID_POINTER); 826 310 AssertPtrReturn(pSrcCfg, VERR_INVALID_POINTER); 827 311 828 #ifdef VBOX_STRICT 829 /** @todo r=bird: This is _bad_ as it makes strict builds behave different from 830 * release builds. The whole 'valid' concept is a bit inconsistent 831 * too, so it cannot carry over to PDM. */ 832 if (!DrvAudioHlpStreamCfgIsValid(pSrcCfg)) 833 { 834 AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pSrcCfg->szName, pSrcCfg)); 835 return VERR_INVALID_PARAMETER; 836 } 837 #endif 312 /* This used to be VBOX_STRICT only and return VERR_INVALID_PARAMETER, but 313 that's making release builds work differently from debug & strict builds, 314 which is a terrible idea: */ 315 Assert(PDMAudioStrmCfgIsValid(pSrcCfg)); 838 316 839 317 memcpy(pDstCfg, pSrcCfg, sizeof(PDMAUDIOSTREAMCFG)); … … 850 328 * @param pCfg The audio stream configuration to duplicate. 851 329 */ 852 PPDMAUDIOSTREAMCFGPDMAudioStrmCfgDup(PCPDMAUDIOSTREAMCFG pCfg)330 DECLINLINE(PPDMAUDIOSTREAMCFG) PDMAudioStrmCfgDup(PCPDMAUDIOSTREAMCFG pCfg) 853 331 { 854 332 AssertPtrReturn(pCfg, NULL); … … 871 349 * @param pCfg The stream configuration to log. 872 350 */ 873 voidPDMAudioStrmCfgLog(PCPDMAUDIOSTREAMCFG pCfg)351 DECLINLINE(void) PDMAudioStrmCfgLog(PCPDMAUDIOSTREAMCFG pCfg) 874 352 { 875 353 if (pCfg) … … 882 360 * 883 361 * @returns Pointer to read-only stream command name on success, 884 * " Unknown" if invalid command value.362 * "bad" if invalid command value. 885 363 * @param enmCmd The stream command to name. 886 364 */ 887 const char *PDMAudioStrmCmdGetName(PDMAUDIOSTREAMCMD enmCmd)365 DECLINLINE(const char *) PDMAudioStrmCmdGetName(PDMAUDIOSTREAMCMD enmCmd) 888 366 { 889 367 switch (enmCmd) … … 901 379 /* no default! */ 902 380 } 903 AssertMsgFailedReturn(("Invalid stream command %d\n", enmCmd), " Unknown");381 AssertMsgFailedReturn(("Invalid stream command %d\n", enmCmd), "bad"); 904 382 } 905 383 … … 910 388 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX. 911 389 */ 912 boolPDMAudioStrmStatusCanRead(PDMAUDIOSTREAMSTS fStatus)390 DECLINLINE(bool) PDMAudioStrmStatusCanRead(PDMAUDIOSTREAMSTS fStatus) 913 391 { 914 392 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); … … 932 410 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX. 933 411 */ 934 boolPDMAudioStrmStatusCanWrite(PDMAUDIOSTREAMSTS fStatus)412 DECLINLINE(bool) PDMAudioStrmStatusCanWrite(PDMAUDIOSTREAMSTS fStatus) 935 413 { 936 414 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); … … 956 434 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX. 957 435 */ 958 boolPDMAudioStrmStatusIsReady(PDMAUDIOSTREAMSTS fStatus)436 DECLINLINE(bool) PDMAudioStrmStatusIsReady(PDMAUDIOSTREAMSTS fStatus) 959 437 { 960 438 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false); … … 970 448 } 971 449 972 /**973 * Calculates the audio bit rate of the given bits per sample, the Hz and the number974 * of audio channels.975 *976 * Divide the result by 8 to get the byte rate.977 *978 * @returns Bitrate.979 * @param cBits Number of bits per sample.980 * @param uHz Hz (Hertz) rate.981 * @param cChannels Number of audio channels.982 */983 uint32_t DrvAudioHlpCalcBitrate(uint8_t cBits, uint32_t uHz, uint8_t cChannels)984 {985 return cBits * uHz * cChannels;986 }987 988 450 989 451 /********************************************************************************************************************************* … … 999 461 * @param pProps PCM properties to calculate bitrate for. 1000 462 */ 1001 uint32_tPDMAudioPropsGetBitrate(PCPDMAUDIOPCMPROPS pProps)463 DECLINLINE(uint32_t) PDMAudioPropsGetBitrate(PCPDMAUDIOPCMPROPS pProps) 1002 464 { 1003 465 return pProps->cbSample * pProps->cChannels * pProps->uHz * 8; … … 1011 473 * @param cb The size (in bytes) to round. 1012 474 */ 1013 uint32_tPDMAudioPropsFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)475 DECLINLINE(uint32_t) PDMAudioPropsFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1014 476 { 1015 477 AssertPtrReturn(pProps, 0); … … 1024 486 * @param cb The size (in bytes) to check. 1025 487 */ 1026 boolPDMAudioPropsIsSizeAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)488 DECLINLINE(bool) PDMAudioPropsIsSizeAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1027 489 { 1028 490 AssertPtrReturn(pProps, false); … … 1039 501 * @param cb The number of bytes to convert. 1040 502 */ 1041 uint32_tPDMAudioPropsBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)503 DECLINLINE(uint32_t) PDMAudioPropsBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1042 504 { 1043 505 AssertPtrReturn(pProps, 0); … … 1054 516 * @note Rounds up the result. 1055 517 */ 1056 uint64_tPDMAudioPropsBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)518 DECLINLINE(uint64_t) PDMAudioPropsBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1057 519 { 1058 520 AssertPtrReturn(pProps, 0); … … 1084 546 * @note Rounds up the result. 1085 547 */ 1086 uint64_tPDMAudioPropsBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)548 DECLINLINE(uint64_t) PDMAudioPropsBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1087 549 { 1088 550 AssertPtrReturn(pProps, 0); … … 1114 576 * @note Rounds up the result. 1115 577 */ 1116 uint64_tPDMAudioPropsBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)578 DECLINLINE(uint64_t) PDMAudioPropsBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb) 1117 579 { 1118 580 AssertPtrReturn(pProps, 0); … … 1143 605 * @sa PDMAUDIOPCMPROPS_F2B 1144 606 */ 1145 uint32_tPDMAudioPropsFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)607 DECLINLINE(uint32_t) PDMAudioPropsFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1146 608 { 1147 609 AssertPtrReturn(pProps, 0); … … 1157 619 * @note No rounding here, result is floored. 1158 620 */ 1159 uint64_tPDMAudioPropsFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)621 DECLINLINE(uint64_t) PDMAudioPropsFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1160 622 { 1161 623 AssertPtrReturn(pProps, 0); … … 1176 638 * @note No rounding here, result is floored. 1177 639 */ 1178 uint64_tPDMAudioPropsFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)640 DECLINLINE(uint64_t) PDMAudioPropsFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames) 1179 641 { 1180 642 AssertPtrReturn(pProps, 0); … … 1196 658 * @note The result is rounded rather than floored (hysterical raisins). 1197 659 */ 1198 uint32_tPDMAudioPropsMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)660 DECLINLINE(uint32_t) PDMAudioPropsMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs) 1199 661 { 1200 662 AssertPtrReturn(pProps, 0); … … 1222 684 * @note The result is rounded rather than floored (hysterical raisins). 1223 685 */ 1224 uint32_tPDMAudioPropsMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)686 DECLINLINE(uint32_t) PDMAudioPropsMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs) 1225 687 { 1226 688 return PDMAUDIOPCMPROPS_F2B(pProps, PDMAudioPropsMilliToFrames(pProps, cMs)); … … 1236 698 * @note The result is rounded rather than floored (hysterical raisins). 1237 699 */ 1238 uint32_tPDMAudioPropsNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)700 DECLINLINE(uint32_t) PDMAudioPropsNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs) 1239 701 { 1240 702 AssertPtrReturn(pProps, 0); … … 1262 724 * @note The result is rounded rather than floored (hysterical raisins). 1263 725 */ 1264 uint32_tPDMAudioPropsNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)726 DECLINLINE(uint32_t) PDMAudioPropsNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs) 1265 727 { 1266 728 return PDMAUDIOPCMPROPS_F2B(pProps, PDMAudioPropsNanoToFrames(pProps, cNs)); … … 1279 741 * uninitialized in some configurations. 1280 742 */ 1281 voidPDMAudioPropsClearBuffer(PCPDMAUDIOPCMPROPS pProps, void *pvBuf, size_t cbBuf, uint32_t cFrames)743 DECLINLINE(void) PDMAudioPropsClearBuffer(PCPDMAUDIOPCMPROPS pProps, void *pvBuf, size_t cbBuf, uint32_t cFrames) 1282 744 { 1283 745 /* … … 1342 804 * @param pProps2 The second set of properties to compare. 1343 805 */ 1344 boolPDMAudioPropsAreEqual(PCPDMAUDIOPCMPROPS pProps1, PCPDMAUDIOPCMPROPS pProps2)806 DECLINLINE(bool) PDMAudioPropsAreEqual(PCPDMAUDIOPCMPROPS pProps1, PCPDMAUDIOPCMPROPS pProps2) 1345 807 { 1346 808 AssertPtrReturn(pProps1, false); … … 1358 820 1359 821 /** 1360 * Checks whether given PCM properties are valid or not. 1361 * 1362 * @note This is more of a supported than valid check. There is code for 1363 * unsigned samples elsewhere (like DrvAudioHlpClearBuf()), but this 1364 * function will flag such properties as not valid. 1365 * 1366 * @todo r=bird: See note and explain properly. 1367 * 1368 * @returns @c true if the properties are valid, @c false if not. 1369 * @param pProps The PCM properties to check. 1370 */ 1371 bool DrvAudioHlpPcmPropsAreValid(PCPDMAUDIOPCMPROPS pProps) 822 * Checks whether the given PCM properties are valid or not. 823 * 824 * @returns true/false accordingly. 825 * @param pProps The PCM properties to check. 826 * 827 * @remarks This just performs a generic check of value ranges. Further, it 828 * will assert if the input is invalid. 829 * 830 * @sa PDMAudioStrmCfgIsValid 831 */ 832 DECLINLINE(bool) PDMAudioPropsAreValid(PCPDMAUDIOPCMPROPS pProps) 1372 833 { 1373 834 AssertPtrReturn(pProps, false); 1374 835 1375 /** @todo r=bird: This code is cannot make up its mind whether to return on 1376 * false, or whether to return at the end. (hint: just return 1377 * immediately, duh.) */ 1378 1379 /* Minimum 1 channel (mono), maximum 7.1 (= 8) channels. */ 1380 bool fValid = ( pProps->cChannels >= 1 1381 && pProps->cChannels <= 8); 1382 1383 if (fValid) 1384 { 1385 switch (pProps->cbSample) 1386 { 1387 case 1: /* 8 bit */ 1388 if (pProps->fSigned) 1389 fValid = false; 1390 break; 1391 case 2: /* 16 bit */ 1392 if (!pProps->fSigned) 1393 fValid = false; 1394 break; 1395 /** @todo Do we need support for 24 bit samples? */ 1396 case 4: /* 32 bit */ 1397 if (!pProps->fSigned) 1398 fValid = false; 1399 break; 1400 default: 1401 fValid = false; 1402 break; 1403 } 1404 } 1405 1406 if (!fValid) 1407 return false; 1408 1409 fValid &= pProps->uHz > 0; 1410 fValid &= pProps->cShift == PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cbSample, pProps->cChannels); 1411 fValid &= pProps->fSwapEndian == false; /** @todo Handling Big Endian audio data is not supported yet. */ 1412 1413 return fValid; 836 AssertReturn(pProps->cChannels != 0, false); 837 AssertMsgReturn(pProps->cbSample == 1 || pProps->cbSample == 2 || pProps->cbSample == 4, 838 ("%u\n", pProps->cbSample), false); 839 AssertMsgReturn(pProps->uHz >= 1000 && pProps->uHz < 1000000, ("%u\n", pProps->uHz), false); 840 AssertMsgReturn(pProps->cShift == PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cbSample, pProps->cChannels), 841 ("cShift=%u cbSample=%u cChannels=%u\n", pProps->cShift, pProps->cbSample, pProps->cChannels), 842 false); 843 return true; 1414 844 } 1415 845 … … 1421 851 * @sa PDMAUDIOPCMPROPS_F2B 1422 852 */ 1423 uint32_tPDMAudioPropsBytesPerFrame(PCPDMAUDIOPCMPROPS pProps)853 DECLINLINE(uint32_t) PDMAudioPropsBytesPerFrame(PCPDMAUDIOPCMPROPS pProps) 1424 854 { 1425 855 return PDMAUDIOPCMPROPS_F2B(pProps, 1 /*cFrames*/); … … 1431 861 * @param pProps Stream configuration to log. 1432 862 */ 1433 voidPDMAudioPropsLog(PCPDMAUDIOPCMPROPS pProps)863 DECLINLINE(void) PDMAudioPropsLog(PCPDMAUDIOPCMPROPS pProps) 1434 864 { 1435 865 AssertPtrReturnVoid(pProps); … … 1439 869 } 1440 870 1441 1442 /*********************************************************************************************************************************1443 * Audio File Helpers *1444 *********************************************************************************************************************************/1445 1446 /**1447 * Sanitizes the file name component so that unsupported characters1448 * will be replaced by an underscore ("_").1449 *1450 * @return IPRT status code.1451 * @param pszPath Path to sanitize.1452 * @param cbPath Size (in bytes) of path to sanitize.1453 */1454 int DrvAudioHlpFileNameSanitize(char *pszPath, size_t cbPath)1455 {1456 RT_NOREF(cbPath);1457 int rc = VINF_SUCCESS;1458 #ifdef RT_OS_WINDOWS1459 /* Filter out characters not allowed on Windows platforms, put in by1460 RTTimeSpecToString(). */1461 /** @todo Use something like RTPathSanitize() if available later some time. */1462 static RTUNICP const s_uszValidRangePairs[] =1463 {1464 ' ', ' ',1465 '(', ')',1466 '-', '.',1467 '0', '9',1468 'A', 'Z',1469 'a', 'z',1470 '_', '_',1471 0xa0, 0xd7af,1472 '\0'1473 };1474 ssize_t cReplaced = RTStrPurgeComplementSet(pszPath, s_uszValidRangePairs, '_' /* Replacement */);1475 if (cReplaced < 0)1476 rc = VERR_INVALID_UTF8_ENCODING;1477 #else1478 RT_NOREF(pszPath);1479 871 #endif 1480 return rc;1481 }1482 1483 /**1484 * Constructs an unique file name, based on the given path and the audio file type.1485 *1486 * @returns IPRT status code.1487 * @param pszFile Where to store the constructed file name.1488 * @param cchFile Size (in characters) of the file name buffer.1489 * @param pszPath Base path to use.1490 * If NULL or empty, the system's temporary directory will be used.1491 * @param pszName A name for better identifying the file.1492 * @param uInstance Device / driver instance which is using this file.1493 * @param enmType Audio file type to construct file name for.1494 * @param fFlags File naming flags, PDMAUDIOFILENAME_FLAGS_XXX.1495 */1496 int DrvAudioHlpFileNameGet(char *pszFile, size_t cchFile, const char *pszPath, const char *pszName,1497 uint32_t uInstance, PDMAUDIOFILETYPE enmType, uint32_t fFlags)1498 {1499 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);1500 AssertReturn(cchFile, VERR_INVALID_PARAMETER);1501 /* pszPath can be NULL. */1502 AssertPtrReturn(pszName, VERR_INVALID_POINTER);1503 /** @todo Validate fFlags. */1504 1505 int rc;1506 1507 char *pszPathTmp = NULL;1508 1509 do1510 {1511 if ( pszPath == NULL1512 || !strlen(pszPath))1513 {1514 char szTemp[RTPATH_MAX];1515 rc = RTPathTemp(szTemp, sizeof(szTemp));1516 if (RT_SUCCESS(rc))1517 {1518 pszPathTmp = RTStrDup(szTemp);1519 }1520 else1521 break;1522 }1523 else1524 pszPathTmp = RTStrDup(pszPath);1525 1526 AssertPtrBreakStmt(pszPathTmp, rc = VERR_NO_MEMORY);1527 1528 char szFilePath[RTPATH_MAX];1529 rc = RTStrCopy(szFilePath, sizeof(szFilePath), pszPathTmp);1530 AssertRCBreak(rc);1531 1532 /* Create it when necessary. */1533 if (!RTDirExists(szFilePath))1534 {1535 rc = RTDirCreateFullPath(szFilePath, RTFS_UNIX_IRWXU);1536 if (RT_FAILURE(rc))1537 break;1538 }1539 1540 char szFileName[RTPATH_MAX];1541 szFileName[0] = '\0';1542 1543 if (fFlags & PDMAUDIOFILENAME_FLAGS_TS)1544 {1545 RTTIMESPEC time;1546 if (!RTTimeSpecToString(RTTimeNow(&time), szFileName, sizeof(szFileName)))1547 {1548 rc = VERR_BUFFER_OVERFLOW;1549 break;1550 }1551 1552 rc = DrvAudioHlpFileNameSanitize(szFileName, sizeof(szFileName));1553 if (RT_FAILURE(rc))1554 break;1555 1556 rc = RTStrCat(szFileName, sizeof(szFileName), "-");1557 if (RT_FAILURE(rc))1558 break;1559 }1560 1561 rc = RTStrCat(szFileName, sizeof(szFileName), pszName);1562 if (RT_FAILURE(rc))1563 break;1564 1565 rc = RTStrCat(szFileName, sizeof(szFileName), "-");1566 if (RT_FAILURE(rc))1567 break;1568 1569 char szInst[16];1570 RTStrPrintf2(szInst, sizeof(szInst), "%RU32", uInstance);1571 rc = RTStrCat(szFileName, sizeof(szFileName), szInst);1572 if (RT_FAILURE(rc))1573 break;1574 1575 switch (enmType)1576 {1577 case PDMAUDIOFILETYPE_RAW:1578 rc = RTStrCat(szFileName, sizeof(szFileName), ".pcm");1579 break;1580 1581 case PDMAUDIOFILETYPE_WAV:1582 rc = RTStrCat(szFileName, sizeof(szFileName), ".wav");1583 break;1584 1585 default:1586 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);1587 break;1588 }1589 1590 if (RT_FAILURE(rc))1591 break;1592 1593 rc = RTPathAppend(szFilePath, sizeof(szFilePath), szFileName);1594 if (RT_FAILURE(rc))1595 break;1596 1597 rc = RTStrCopy(pszFile, cchFile, szFilePath);1598 1599 } while (0);1600 1601 RTStrFree(pszPathTmp);1602 1603 LogFlowFuncLeaveRC(rc);1604 return rc;1605 }1606 1607 /**1608 * Creates an audio file.1609 *1610 * @returns IPRT status code.1611 * @param enmType Audio file type to open / create.1612 * @param pszFile File path of file to open or create.1613 * @param fFlags Audio file flags, PDMAUDIOFILE_FLAGS_XXX.1614 * @param ppFile Where to store the created audio file handle.1615 * Needs to be destroyed with DrvAudioHlpFileDestroy().1616 */1617 int DrvAudioHlpFileCreate(PDMAUDIOFILETYPE enmType, const char *pszFile, uint32_t fFlags, PPDMAUDIOFILE *ppFile)1618 {1619 AssertPtrReturn(pszFile, VERR_INVALID_POINTER);1620 /** @todo Validate fFlags. */1621 1622 PPDMAUDIOFILE pFile = (PPDMAUDIOFILE)RTMemAlloc(sizeof(PDMAUDIOFILE));1623 if (!pFile)1624 return VERR_NO_MEMORY;1625 1626 int rc = VINF_SUCCESS;1627 1628 switch (enmType)1629 {1630 case PDMAUDIOFILETYPE_RAW:1631 case PDMAUDIOFILETYPE_WAV:1632 pFile->enmType = enmType;1633 break;1634 1635 default:1636 rc = VERR_INVALID_PARAMETER;1637 break;1638 }1639 1640 if (RT_SUCCESS(rc))1641 {1642 RTStrPrintf(pFile->szName, RT_ELEMENTS(pFile->szName), "%s", pszFile);1643 pFile->hFile = NIL_RTFILE;1644 pFile->fFlags = fFlags;1645 pFile->pvData = NULL;1646 pFile->cbData = 0;1647 }1648 1649 if (RT_FAILURE(rc))1650 {1651 RTMemFree(pFile);1652 pFile = NULL;1653 }1654 else1655 *ppFile = pFile;1656 1657 return rc;1658 }1659 1660 /**1661 * Destroys a formerly created audio file.1662 *1663 * @param pFile Audio file (object) to destroy.1664 */1665 void DrvAudioHlpFileDestroy(PPDMAUDIOFILE pFile)1666 {1667 if (!pFile)1668 return;1669 1670 DrvAudioHlpFileClose(pFile);1671 1672 RTMemFree(pFile);1673 pFile = NULL;1674 }1675 1676 /**1677 * Opens or creates an audio file.1678 *1679 * @returns IPRT status code.1680 * @param pFile Pointer to audio file handle to use.1681 * @param fOpen Open flags.1682 * Use PDMAUDIOFILE_DEFAULT_OPEN_FLAGS for the default open flags.1683 * @param pProps PCM properties to use.1684 */1685 int DrvAudioHlpFileOpen(PPDMAUDIOFILE pFile, uint32_t fOpen, PCPDMAUDIOPCMPROPS pProps)1686 {1687 AssertPtrReturn(pFile, VERR_INVALID_POINTER);1688 /** @todo Validate fOpen flags. */1689 AssertPtrReturn(pProps, VERR_INVALID_POINTER);1690 1691 int rc;1692 1693 if (pFile->enmType == PDMAUDIOFILETYPE_RAW)1694 {1695 rc = RTFileOpen(&pFile->hFile, pFile->szName, fOpen);1696 }1697 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)1698 {1699 Assert(pProps->cChannels);1700 Assert(pProps->uHz);1701 Assert(pProps->cbSample);1702 1703 pFile->pvData = (PAUDIOWAVFILEDATA)RTMemAllocZ(sizeof(AUDIOWAVFILEDATA));1704 if (pFile->pvData)1705 {1706 pFile->cbData = sizeof(PAUDIOWAVFILEDATA);1707 1708 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;1709 AssertPtr(pData);1710 1711 /* Header. */1712 pData->Hdr.u32RIFF = AUDIO_MAKE_FOURCC('R','I','F','F');1713 pData->Hdr.u32Size = 36;1714 pData->Hdr.u32WAVE = AUDIO_MAKE_FOURCC('W','A','V','E');1715 1716 pData->Hdr.u32Fmt = AUDIO_MAKE_FOURCC('f','m','t',' ');1717 pData->Hdr.u32Size1 = 16; /* Means PCM. */1718 pData->Hdr.u16AudioFormat = 1; /* PCM, linear quantization. */1719 pData->Hdr.u16NumChannels = pProps->cChannels;1720 pData->Hdr.u32SampleRate = pProps->uHz;1721 pData->Hdr.u32ByteRate = PDMAudioPropsGetBitrate(pProps) / 8;1722 pData->Hdr.u16BlockAlign = pProps->cChannels * pProps->cbSample;1723 pData->Hdr.u16BitsPerSample = pProps->cbSample * 8;1724 1725 /* Data chunk. */1726 pData->Hdr.u32ID2 = AUDIO_MAKE_FOURCC('d','a','t','a');1727 pData->Hdr.u32Size2 = 0;1728 1729 rc = RTFileOpen(&pFile->hFile, pFile->szName, fOpen);1730 if (RT_SUCCESS(rc))1731 {1732 rc = RTFileWrite(pFile->hFile, &pData->Hdr, sizeof(pData->Hdr), NULL);1733 if (RT_FAILURE(rc))1734 {1735 RTFileClose(pFile->hFile);1736 pFile->hFile = NIL_RTFILE;1737 }1738 }1739 1740 if (RT_FAILURE(rc))1741 {1742 RTMemFree(pFile->pvData);1743 pFile->pvData = NULL;1744 pFile->cbData = 0;1745 }1746 }1747 else1748 rc = VERR_NO_MEMORY;1749 }1750 else1751 rc = VERR_INVALID_PARAMETER;1752 1753 if (RT_SUCCESS(rc))1754 {1755 LogRel2(("Audio: Opened file '%s'\n", pFile->szName));1756 }1757 else1758 LogRel(("Audio: Failed opening file '%s', rc=%Rrc\n", pFile->szName, rc));1759 1760 return rc;1761 }1762 1763 /**1764 * Closes an audio file.1765 *1766 * @returns IPRT status code.1767 * @param pFile Audio file handle to close.1768 */1769 int DrvAudioHlpFileClose(PPDMAUDIOFILE pFile)1770 {1771 if (!pFile)1772 return VINF_SUCCESS;1773 1774 size_t cbSize = DrvAudioHlpFileGetDataSize(pFile);1775 1776 int rc = VINF_SUCCESS;1777 1778 if (pFile->enmType == PDMAUDIOFILETYPE_RAW)1779 {1780 if (RTFileIsValid(pFile->hFile))1781 rc = RTFileClose(pFile->hFile);1782 }1783 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)1784 {1785 if (RTFileIsValid(pFile->hFile))1786 {1787 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;1788 if (pData) /* The .WAV file data only is valid when a file actually has been created. */1789 {1790 /* Update the header with the current data size. */1791 RTFileWriteAt(pFile->hFile, 0, &pData->Hdr, sizeof(pData->Hdr), NULL);1792 }1793 1794 rc = RTFileClose(pFile->hFile);1795 }1796 1797 if (pFile->pvData)1798 {1799 RTMemFree(pFile->pvData);1800 pFile->pvData = NULL;1801 }1802 }1803 else1804 AssertFailedStmt(rc = VERR_NOT_IMPLEMENTED);1805 1806 if ( RT_SUCCESS(rc)1807 && !cbSize1808 && !(pFile->fFlags & PDMAUDIOFILE_FLAGS_KEEP_IF_EMPTY))1809 {1810 rc = DrvAudioHlpFileDelete(pFile);1811 }1812 1813 pFile->cbData = 0;1814 1815 if (RT_SUCCESS(rc))1816 {1817 pFile->hFile = NIL_RTFILE;1818 LogRel2(("Audio: Closed file '%s' (%zu bytes)\n", pFile->szName, cbSize));1819 }1820 else1821 LogRel(("Audio: Failed closing file '%s', rc=%Rrc\n", pFile->szName, rc));1822 1823 return rc;1824 }1825 1826 /**1827 * Deletes an audio file.1828 *1829 * @returns IPRT status code.1830 * @param pFile Audio file handle to delete.1831 */1832 int DrvAudioHlpFileDelete(PPDMAUDIOFILE pFile)1833 {1834 AssertPtrReturn(pFile, VERR_INVALID_POINTER);1835 1836 int rc = RTFileDelete(pFile->szName);1837 if (RT_SUCCESS(rc))1838 {1839 LogRel2(("Audio: Deleted file '%s'\n", pFile->szName));1840 }1841 else if (rc == VERR_FILE_NOT_FOUND) /* Don't bitch if the file is not around (anymore). */1842 rc = VINF_SUCCESS;1843 1844 if (RT_FAILURE(rc))1845 LogRel(("Audio: Failed deleting file '%s', rc=%Rrc\n", pFile->szName, rc));1846 1847 return rc;1848 }1849 1850 /**1851 * Returns the raw audio data size of an audio file.1852 *1853 * Note: This does *not* include file headers and other data which does1854 * not belong to the actual PCM audio data.1855 *1856 * @returns Size (in bytes) of the raw PCM audio data.1857 * @param pFile Audio file handle to retrieve the audio data size for.1858 */1859 size_t DrvAudioHlpFileGetDataSize(PPDMAUDIOFILE pFile)1860 {1861 AssertPtrReturn(pFile, 0);1862 1863 size_t cbSize = 0;1864 1865 if (pFile->enmType == PDMAUDIOFILETYPE_RAW)1866 {1867 cbSize = RTFileTell(pFile->hFile);1868 }1869 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)1870 {1871 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;1872 if (pData) /* The .WAV file data only is valid when a file actually has been created. */1873 cbSize = pData->Hdr.u32Size2;1874 }1875 1876 return cbSize;1877 }1878 1879 /**1880 * Returns whether the given audio file is open and in use or not.1881 *1882 * @return bool True if open, false if not.1883 * @param pFile Audio file handle to check open status for.1884 */1885 bool DrvAudioHlpFileIsOpen(PPDMAUDIOFILE pFile)1886 {1887 if (!pFile)1888 return false;1889 1890 return RTFileIsValid(pFile->hFile);1891 }1892 1893 /**1894 * Write PCM data to a wave (.WAV) file.1895 *1896 * @returns IPRT status code.1897 * @param pFile Audio file handle to write PCM data to.1898 * @param pvBuf Audio data to write.1899 * @param cbBuf Size (in bytes) of audio data to write.1900 * @param fFlags Additional write flags. Not being used at the moment and must be 0.1901 */1902 int DrvAudioHlpFileWrite(PPDMAUDIOFILE pFile, const void *pvBuf, size_t cbBuf, uint32_t fFlags)1903 {1904 AssertPtrReturn(pFile, VERR_INVALID_POINTER);1905 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);1906 1907 AssertReturn(fFlags == 0, VERR_INVALID_PARAMETER); /** @todo fFlags are currently not implemented. */1908 1909 if (!cbBuf)1910 return VINF_SUCCESS;1911 1912 AssertReturn(RTFileIsValid(pFile->hFile), VERR_WRONG_ORDER);1913 1914 int rc;1915 1916 if (pFile->enmType == PDMAUDIOFILETYPE_RAW)1917 {1918 rc = RTFileWrite(pFile->hFile, pvBuf, cbBuf, NULL);1919 }1920 else if (pFile->enmType == PDMAUDIOFILETYPE_WAV)1921 {1922 PAUDIOWAVFILEDATA pData = (PAUDIOWAVFILEDATA)pFile->pvData;1923 AssertPtr(pData);1924 1925 rc = RTFileWrite(pFile->hFile, pvBuf, cbBuf, NULL);1926 if (RT_SUCCESS(rc))1927 {1928 pData->Hdr.u32Size += (uint32_t)cbBuf;1929 pData->Hdr.u32Size2 += (uint32_t)cbBuf;1930 }1931 }1932 else1933 rc = VERR_NOT_SUPPORTED;1934 1935 return rc;1936 }1937 -
trunk/src/VBox/Devices/Audio/AudioMixer.cpp
r88026 r88028 80 80 #include <VBox/vmm/mm.h> 81 81 #include <VBox/vmm/pdmaudioifs.h> 82 #include <VBox/vmm/pdmaudioinline.h> 82 83 83 84 #include <iprt/alloc.h> -
trunk/src/VBox/Devices/Audio/DevHDA.cpp
r88027 r88028 29 29 #include <VBox/vmm/pdmdev.h> 30 30 #include <VBox/vmm/pdmaudioifs.h> 31 #include <VBox/vmm/pdmaudioinline.h> 31 32 #ifdef HDA_DEBUG_GUEST_RIP 32 33 # include <VBox/vmm/cpum.h> -
trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
r88027 r88028 24 24 #include <VBox/vmm/pdmdev.h> 25 25 #include <VBox/vmm/pdmaudioifs.h> 26 #include <VBox/vmm/pdmaudioinline.h> 26 27 27 28 #include <iprt/assert.h> -
trunk/src/VBox/Devices/Audio/DevSB16.cpp
r88025 r88028 56 56 #include <VBox/vmm/pdmdev.h> 57 57 #include <VBox/vmm/pdmaudioifs.h> 58 #include <VBox/vmm/pdmaudioinline.h> 58 59 #include <VBox/AssertGuest.h> 59 60 -
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r88026 r88028 19 19 */ 20 20 21 /********************************************************************************************************************************* 22 * Header Files * 23 *********************************************************************************************************************************/ 21 24 #define LOG_GROUP LOG_GROUP_DRV_AUDIO 22 25 #include <VBox/log.h> … … 25 28 #include <VBox/vmm/mm.h> 26 29 #include <VBox/vmm/pdmaudioifs.h> 30 #include <VBox/vmm/pdmaudioinline.h> 27 31 28 32 #include <iprt/alloc.h> … … 41 45 #include "AudioMixBuffer.h" 42 46 47 48 /********************************************************************************************************************************* 49 * Internal Functions * 50 *********************************************************************************************************************************/ 43 51 #ifdef VBOX_WITH_AUDIO_ENUM 44 52 static int drvAudioDevicesEnumerateInternal(PDRVAUDIO pThis, bool fLog, PPDMAUDIODEVICEENUM pDevEnum); … … 56 64 static void drvAudioStreamDropInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 57 65 static void drvAudioStreamResetInternal(PDRVAUDIO pThis, PPDMAUDIOSTREAM pStream); 66 58 67 59 68 #ifndef VBOX_AUDIO_TESTCASE -
trunk/src/VBox/Devices/Audio/DrvAudio.h
r88027 r88028 185 185 ( (PDRVAUDIO)((uintptr_t)pInterface - RT_UOFFSETOF(DRVAUDIO, IAudioConnector)) ) 186 186 187 /** @name Audio format helper methods.188 * @{ */189 const char *PDMAudioDirGetName(PDMAUDIODIR enmDir);190 const char *PDMAudioFormatGetName(PDMAUDIOFMT enmFmt);191 bool PDMAudioFormatIsSigned(PDMAUDIOFMT enmFmt);192 uint8_t PDMAudioFormatGetBits(PDMAUDIOFMT enmFmt);193 /** @} */194 195 187 /** @name Audio calculation helper methods. 196 188 * @{ */ … … 200 192 /** @name Audio PCM properties helper methods. 201 193 * @{ */ 202 void PDMAudioPropsClearBuffer(PCPDMAUDIOPCMPROPS pProps, void *pvBuf, size_t cbBuf, uint32_t cFrames);203 uint32_t PDMAudioPropsGetBitrate(PCPDMAUDIOPCMPROPS pProps);204 uint32_t PDMAudioPropsFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb);205 bool PDMAudioPropsIsSizeAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb);206 uint32_t PDMAudioPropsBytesPerFrame(PCPDMAUDIOPCMPROPS pProps);207 uint32_t PDMAudioPropsBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb);208 uint64_t PDMAudioPropsBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb);209 uint64_t PDMAudioPropsBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb);210 uint64_t PDMAudioPropsBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb);211 uint32_t PDMAudioPropsFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);212 uint64_t PDMAudioPropsFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);213 uint64_t PDMAudioPropsFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames);214 uint32_t PDMAudioPropsMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs);215 uint32_t PDMAudioPropsNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs);216 uint32_t PDMAudioPropsMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs);217 uint32_t PDMAudioPropsNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs);218 219 bool PDMAudioPropsAreEqual(PCPDMAUDIOPCMPROPS pPCMProps1, PCPDMAUDIOPCMPROPS pPCMProps2);220 void PDMAudioPropsLog(PCPDMAUDIOPCMPROPS pProps);221 222 194 bool DrvAudioHlpPcmPropsAreValid(PCPDMAUDIOPCMPROPS pProps); 223 195 /** @} */ … … 225 197 /** @name Audio configuration helper methods. 226 198 * @{ */ 227 void PDMAudioStrmCfgInit(PPDMAUDIOSTREAMCFG pCfg);228 int PDMAudioStrmCfgInitWithProps(PPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps);229 bool PDMAudioStrmCfgMatchesProps(PCPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps);230 int PDMAudioStrmCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg);231 PPDMAUDIOSTREAMCFG PDMAudioStrmCfgDup(PCPDMAUDIOSTREAMCFG pCfg);232 void PDMAudioStrmCfgFree(PPDMAUDIOSTREAMCFG pCfg);233 void PDMAudioStrmCfgLog(PCPDMAUDIOSTREAMCFG pCfg);234 235 199 bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg); 236 /** @} */237 238 /** @name Audio stream command helper methods.239 * @{ */240 const char *PDMAudioStrmCmdGetName(PDMAUDIOSTREAMCMD enmCmd);241 /** @} */242 243 /** @name Audio stream status helper methods.244 * @{ */245 bool PDMAudioStrmStatusCanRead(PDMAUDIOSTREAMSTS fStatus);246 bool PDMAudioStrmStatusCanWrite(PDMAUDIOSTREAMSTS fStatus);247 bool PDMAudioStrmStatusIsReady(PDMAUDIOSTREAMSTS fStatus);248 200 /** @} */ 249 201 … … 279 231 /** @name Audio string-ify methods. 280 232 * @{ */ 281 const char *PDMAudioMixerCtlGetName(PDMAUDIOMIXERCTL enmMixerCtl);282 const char *PDMAudioPlaybackDstGetName(const PDMAUDIOPLAYBACKDST enmPlaybackDst);283 const char *PDMAudioRecSrcGetName(const PDMAUDIORECSRC enmRecSource);284 233 PDMAUDIOFMT DrvAudioHlpStrToAudFmt(const char *pszFmt); 285 234 char *DrvAudioHlpAudDevFlagsToStrA(uint32_t fFlags); -
trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp
r88027 r88028 37 37 #include <VBox/vmm/pdmdev.h> 38 38 #include <VBox/vmm/pdm.h> 39 #include <VBox/vmm/pdmaudioinline.h> 39 40 #include <VBox/vmm/mm.h> 40 41 … … 468 469 RTStrFree(pszFlags); 469 470 } 470 }471 472 /**473 * Gets the name of an audio direction enum value.474 *475 * @returns Pointer to read-only name string on success, "Unknown" if476 * passed an invalid enum value.477 * @param enmDir The audio direction value to name.478 */479 const char *PDMAudioDirGetName(PDMAUDIODIR enmDir)480 {481 switch (enmDir)482 {483 case PDMAUDIODIR_UNKNOWN: return "Unknown";484 case PDMAUDIODIR_IN: return "Input";485 case PDMAUDIODIR_OUT: return "Output";486 case PDMAUDIODIR_DUPLEX: return "Duplex";487 488 /* no default */489 case PDMAUDIODIR_INVALID:490 case PDMAUDIODIR_32BIT_HACK:491 break;492 }493 AssertMsgFailedReturn(("Invalid audio direction %d\n", enmDir), "Unknown");494 }495 496 /**497 * Converts an audio mixer control to a string.498 *499 * @returns Stringified audio mixer control or "Unknown", if not found.500 * @param enmMixerCtl Audio mixer control to convert.501 */502 const char *PDMAudioMixerCtlGetName(PDMAUDIOMIXERCTL enmMixerCtl)503 {504 switch (enmMixerCtl)505 {506 case PDMAUDIOMIXERCTL_VOLUME_MASTER: return "Master Volume";507 case PDMAUDIOMIXERCTL_FRONT: return "Front";508 case PDMAUDIOMIXERCTL_CENTER_LFE: return "Center / LFE";509 case PDMAUDIOMIXERCTL_REAR: return "Rear";510 case PDMAUDIOMIXERCTL_LINE_IN: return "Line-In";511 case PDMAUDIOMIXERCTL_MIC_IN: return "Microphone-In";512 default: break;513 }514 515 AssertMsgFailed(("Invalid mixer control %ld\n", enmMixerCtl));516 return "Unknown";517 471 } 518 472 … … 571 525 572 526 /** 573 * Converts a playback destination enumeration to a string.574 *575 * @returns Stringified playback destination, or "Unknown", if not found.576 * @param enmPlaybackDst Playback destination to convert.577 */578 const char *PDMAudioPlaybackDstGetName(const PDMAUDIOPLAYBACKDST enmPlaybackDst)579 {580 switch (enmPlaybackDst)581 {582 case PDMAUDIOPLAYBACKDST_UNKNOWN: return "Unknown";583 case PDMAUDIOPLAYBACKDST_FRONT: return "Front";584 case PDMAUDIOPLAYBACKDST_CENTER_LFE: return "Center / LFE";585 case PDMAUDIOPLAYBACKDST_REAR: return "Rear";586 default:587 break;588 }589 590 AssertMsgFailed(("Invalid playback destination %ld\n", enmPlaybackDst));591 return "Unknown";592 }593 594 /**595 * Converts a recording source enumeration to a string.596 *597 * @returns Stringified recording source, or "Unknown", if not found.598 * @param enmRecSrc Recording source to convert.599 */600 const char *PDMAudioRecSrcGetName(const PDMAUDIORECSRC enmRecSrc)601 {602 switch (enmRecSrc)603 {604 case PDMAUDIORECSRC_UNKNOWN: return "Unknown";605 case PDMAUDIORECSRC_MIC: return "Microphone In";606 case PDMAUDIORECSRC_CD: return "CD";607 case PDMAUDIORECSRC_VIDEO: return "Video";608 case PDMAUDIORECSRC_AUX: return "AUX";609 case PDMAUDIORECSRC_LINE: return "Line In";610 case PDMAUDIORECSRC_PHONE: return "Phone";611 default:612 break;613 }614 615 AssertMsgFailed(("Invalid recording source %ld\n", enmRecSrc));616 return "Unknown";617 }618 619 /**620 * Checks whether the audio format is signed.621 *622 * @returns @c true for signed format, @c false for unsigned.623 * @param enmFmt The audio format.624 */625 bool PDMAudioFormatIsSigned(PDMAUDIOFMT enmFmt)626 {627 switch (enmFmt)628 {629 case PDMAUDIOFMT_S8:630 case PDMAUDIOFMT_S16:631 case PDMAUDIOFMT_S32:632 return true;633 634 case PDMAUDIOFMT_U8:635 case PDMAUDIOFMT_U16:636 case PDMAUDIOFMT_U32:637 return false;638 639 /* no default */640 case PDMAUDIOFMT_INVALID:641 case PDMAUDIOFMT_32BIT_HACK:642 break;643 }644 AssertMsgFailedReturn(("Bogus audio format %ld\n", enmFmt), false);645 }646 647 /**648 * Gets the encoding width in bits of the give audio format.649 *650 * @returns Bit count. 0 if invalid input.651 * @param enmFmt The audio format.652 */653 uint8_t PDMAudioFormatGetBits(PDMAUDIOFMT enmFmt)654 {655 switch (enmFmt)656 {657 case PDMAUDIOFMT_S8:658 case PDMAUDIOFMT_U8:659 return 8;660 661 case PDMAUDIOFMT_U16:662 case PDMAUDIOFMT_S16:663 return 16;664 665 case PDMAUDIOFMT_U32:666 case PDMAUDIOFMT_S32:667 return 32;668 669 /* no default */670 case PDMAUDIOFMT_INVALID:671 case PDMAUDIOFMT_32BIT_HACK:672 break;673 }674 AssertMsgFailedReturn(("Bogus audio format %ld\n", enmFmt), 0);675 }676 677 /**678 * Gets the name of an audio format enum value.679 *680 * @returns Pointer to read-only name on success, returns "Unknown" on if681 * invalid enum value.682 * @param enmFmt The audio format to name.683 */684 const char *PDMAudioFormatGetName(PDMAUDIOFMT enmFmt)685 {686 switch (enmFmt)687 {688 case PDMAUDIOFMT_U8: return "U8";689 case PDMAUDIOFMT_U16: return "U16";690 case PDMAUDIOFMT_U32: return "U32";691 case PDMAUDIOFMT_S8: return "S8";692 case PDMAUDIOFMT_S16: return "S16";693 case PDMAUDIOFMT_S32: return "S32";694 /* no default */695 case PDMAUDIOFMT_INVALID:696 case PDMAUDIOFMT_32BIT_HACK:697 break;698 }699 AssertMsgFailedReturn(("Bogus audio format %d\n", enmFmt), "Unknown");700 }701 702 /**703 527 * Converts a given string to an audio format. 704 528 * … … 727 551 } 728 552 729 #if 0 /* unused */730 /**731 * Initializes a stream configuration with default values.732 *733 * @param pCfg The stream configuration structure to initialize.734 */735 void PDMAudioStrmCfgInit(PPDMAUDIOSTREAMCFG pCfg)736 {737 AssertPtrReturnVoid(pCfg);738 739 RT_ZERO(*pCfg);740 741 pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */742 }743 #endif744 745 /**746 * Initializes a stream configuration from PCM properties.747 *748 * @return IPRT status code.749 * @param pCfg The stream configuration to initialize.750 * @param pProps The PCM properties to use.751 */752 int PDMAudioStrmCfgInitWithProps(PPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps)753 {754 AssertPtrReturn(pProps, VERR_INVALID_POINTER);755 AssertPtrReturn(pCfg, VERR_INVALID_POINTER);756 757 RT_ZERO(*pCfg);758 pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */759 760 memcpy(&pCfg->Props, pProps, sizeof(PDMAUDIOPCMPROPS));761 762 return VINF_SUCCESS;763 }764 765 553 /** 766 554 * Checks whether a given stream configuration is valid or not. … … 775 563 AssertPtrReturn(pCfg, false); 776 564 565 AssertReturn(PDMAudioStrmCfgIsValid(pCfg), false); 566 777 567 bool fValid = ( pCfg->enmDir == PDMAUDIODIR_IN 778 568 || pCfg->enmDir == PDMAUDIODIR_OUT); … … 785 575 786 576 return fValid; 787 }788 789 /**790 * Checks whether stream configuration matches the given PCM properties.791 *792 * @returns @c true if equal, @c false if not.793 * @param pCfg The stream configuration.794 * @param pProps The PCM properties to match with.795 */796 bool PDMAudioStrmCfgMatchesProps(PCPDMAUDIOSTREAMCFG pCfg, PCPDMAUDIOPCMPROPS pProps)797 {798 AssertPtrReturn(pCfg, false);799 return PDMAudioPropsAreEqual(pProps, &pCfg->Props);800 }801 802 /**803 * Frees an audio stream allocated by PDMAudioStrmCfgDup().804 *805 * @param pCfg The stream configuration to free.806 */807 void PDMAudioStrmCfgFree(PPDMAUDIOSTREAMCFG pCfg)808 {809 if (pCfg)810 {811 RTMemFree(pCfg);812 pCfg = NULL;813 }814 }815 816 /**817 * Copies one stream configuration to another.818 *819 * @returns IPRT status code.820 * @param pDstCfg The destination stream configuration.821 * @param pSrcCfg The source stream configuration.822 */823 int PDMAudioStrmCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg)824 {825 AssertPtrReturn(pDstCfg, VERR_INVALID_POINTER);826 AssertPtrReturn(pSrcCfg, VERR_INVALID_POINTER);827 828 #ifdef VBOX_STRICT829 /** @todo r=bird: This is _bad_ as it makes strict builds behave different from830 * release builds. The whole 'valid' concept is a bit inconsistent831 * too, so it cannot carry over to PDM. */832 if (!DrvAudioHlpStreamCfgIsValid(pSrcCfg))833 {834 AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pSrcCfg->szName, pSrcCfg));835 return VERR_INVALID_PARAMETER;836 }837 #endif838 839 memcpy(pDstCfg, pSrcCfg, sizeof(PDMAUDIOSTREAMCFG));840 841 return VINF_SUCCESS;842 }843 844 /**845 * Duplicates an audio stream configuration.846 *847 * @returns Pointer to duplicate on success, NULL on failure. Must be freed848 * using PDMAudioStrmCfgFree().849 *850 * @param pCfg The audio stream configuration to duplicate.851 */852 PPDMAUDIOSTREAMCFG PDMAudioStrmCfgDup(PCPDMAUDIOSTREAMCFG pCfg)853 {854 AssertPtrReturn(pCfg, NULL);855 856 PPDMAUDIOSTREAMCFG pDst = (PPDMAUDIOSTREAMCFG)RTMemAllocZ(sizeof(PDMAUDIOSTREAMCFG));857 if (pDst)858 {859 int rc = PDMAudioStrmCfgCopy(pDst, pCfg);860 if (RT_SUCCESS(rc))861 return pDst;862 863 PDMAudioStrmCfgFree(pDst);864 }865 return NULL;866 }867 868 /**869 * Logs an audio stream configuration.870 *871 * @param pCfg The stream configuration to log.872 */873 void PDMAudioStrmCfgLog(PCPDMAUDIOSTREAMCFG pCfg)874 {875 if (pCfg)876 LogFunc(("szName=%s enmDir=%RU32 uHz=%RU32 cBits=%RU8%s cChannels=%RU8\n", pCfg->szName, pCfg->enmDir,877 pCfg->Props.uHz, pCfg->Props.cbSample * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannels));878 }879 880 /**881 * Converts a stream command enum value to a string.882 *883 * @returns Pointer to read-only stream command name on success,884 * "Unknown" if invalid command value.885 * @param enmCmd The stream command to name.886 */887 const char *PDMAudioStrmCmdGetName(PDMAUDIOSTREAMCMD enmCmd)888 {889 switch (enmCmd)890 {891 case PDMAUDIOSTREAMCMD_INVALID: return "Invalid";892 case PDMAUDIOSTREAMCMD_UNKNOWN: return "Unknown";893 case PDMAUDIOSTREAMCMD_ENABLE: return "Enable";894 case PDMAUDIOSTREAMCMD_DISABLE: return "Disable";895 case PDMAUDIOSTREAMCMD_PAUSE: return "Pause";896 case PDMAUDIOSTREAMCMD_RESUME: return "Resume";897 case PDMAUDIOSTREAMCMD_DRAIN: return "Drain";898 case PDMAUDIOSTREAMCMD_DROP: return "Drop";899 case PDMAUDIOSTREAMCMD_32BIT_HACK:900 break;901 /* no default! */902 }903 AssertMsgFailedReturn(("Invalid stream command %d\n", enmCmd), "Unknown");904 }905 906 /**907 * Checks if the stream status is one that can be read from.908 *909 * @returns @c true if ready to be read from, @c false if not.910 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX.911 */912 bool PDMAudioStrmStatusCanRead(PDMAUDIOSTREAMSTS fStatus)913 {914 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);915 /*916 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED917 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED918 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)919 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);*/920 return (fStatus & ( PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED921 | PDMAUDIOSTREAMSTS_FLAGS_ENABLED922 | PDMAUDIOSTREAMSTS_FLAGS_PAUSED923 | PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT ))924 == ( PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED925 | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);926 }927 928 /**929 * Checks if the stream status is one that can be written to.930 *931 * @returns @c true if ready to be written to, @c false if not.932 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX.933 */934 bool PDMAudioStrmStatusCanWrite(PDMAUDIOSTREAMSTS fStatus)935 {936 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);937 /*938 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED939 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED940 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)941 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)942 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);*/943 return (fStatus & ( PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED944 | PDMAUDIOSTREAMSTS_FLAGS_ENABLED945 | PDMAUDIOSTREAMSTS_FLAGS_PAUSED946 | PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE947 | PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT))948 == ( PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED949 | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);950 }951 952 /**953 * Checks if the stream status is a read-to-operate one.954 *955 * @returns @c true if ready to operate, @c false if not.956 * @param fStatus Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX.957 */958 bool PDMAudioStrmStatusIsReady(PDMAUDIOSTREAMSTS fStatus)959 {960 AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);961 /*962 return fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED963 && fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED964 && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);*/965 return (fStatus & ( PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED966 | PDMAUDIOSTREAMSTS_FLAGS_ENABLED967 | PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT))968 == ( PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED969 | PDMAUDIOSTREAMSTS_FLAGS_ENABLED);970 577 } 971 578 … … 987 594 988 595 989 /*********************************************************************************************************************************990 * PCM Property Helpers *991 *********************************************************************************************************************************/992 993 /**994 * Gets the bitrate.995 *996 * Divide the result by 8 to get the byte rate.997 *998 * @returns Bit rate.999 * @param pProps PCM properties to calculate bitrate for.1000 */1001 uint32_t PDMAudioPropsGetBitrate(PCPDMAUDIOPCMPROPS pProps)1002 {1003 return pProps->cbSample * pProps->cChannels * pProps->uHz * 8;1004 }1005 1006 /**1007 * Rounds down the given byte amount to the nearest frame boundrary.1008 *1009 * @returns Rounded byte amount.1010 * @param pProps PCM properties to use.1011 * @param cb The size (in bytes) to round.1012 */1013 uint32_t PDMAudioPropsFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)1014 {1015 AssertPtrReturn(pProps, 0);1016 return PDMAUDIOPCMPROPS_F2B(pProps, PDMAUDIOPCMPROPS_B2F(pProps, cb));1017 }1018 1019 /**1020 * Checks if the given size is aligned on a frame boundrary.1021 *1022 * @returns @c true if properly aligned, @c false if not.1023 * @param pProps PCM properties to use.1024 * @param cb The size (in bytes) to check.1025 */1026 bool PDMAudioPropsIsSizeAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)1027 {1028 AssertPtrReturn(pProps, false);1029 uint32_t const cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);1030 AssertReturn(cbFrame, false);1031 return cb % cbFrame == 0;1032 }1033 1034 /**1035 * Converts bytes to frames (rounding down of course).1036 *1037 * @returns Number of frames.1038 * @param pProps PCM properties to use.1039 * @param cb The number of bytes to convert.1040 */1041 uint32_t PDMAudioPropsBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)1042 {1043 AssertPtrReturn(pProps, 0);1044 return PDMAUDIOPCMPROPS_B2F(pProps, cb);1045 }1046 1047 /**1048 * Converts bytes to milliseconds.1049 *1050 * @return Number milliseconds @a cb takes to play or record.1051 * @param pProps PCM properties to use.1052 * @param cb The number of bytes to convert.1053 *1054 * @note Rounds up the result.1055 */1056 uint64_t PDMAudioPropsBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)1057 {1058 AssertPtrReturn(pProps, 0);1059 1060 /* Check parameters to prevent division by chainsaw: */1061 uint32_t const uHz = pProps->uHz;1062 if (uHz)1063 {1064 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);1065 if (cbFrame)1066 {1067 /* Round cb up to closest frame size: */1068 cb = (cb + cbFrame - 1) / cbFrame;1069 1070 /* Convert to milliseconds. */1071 return (cb * (uint64_t)RT_MS_1SEC + uHz - 1) / uHz;1072 }1073 }1074 return 0;1075 }1076 1077 /**1078 * Converts bytes to microseconds.1079 *1080 * @return Number microseconds @a cb takes to play or record.1081 * @param pProps PCM properties to use.1082 * @param cb The number of bytes to convert.1083 *1084 * @note Rounds up the result.1085 */1086 uint64_t PDMAudioPropsBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)1087 {1088 AssertPtrReturn(pProps, 0);1089 1090 /* Check parameters to prevent division by chainsaw: */1091 uint32_t const uHz = pProps->uHz;1092 if (uHz)1093 {1094 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);1095 if (cbFrame)1096 {1097 /* Round cb up to closest frame size: */1098 cb = (cb + cbFrame - 1) / cbFrame;1099 1100 /* Convert to microseconds. */1101 return (cb * (uint64_t)RT_US_1SEC + uHz - 1) / uHz;1102 }1103 }1104 return 0;1105 }1106 1107 /**1108 * Converts bytes to nanoseconds.1109 *1110 * @return Number nanoseconds @a cb takes to play or record.1111 * @param pProps PCM properties to use.1112 * @param cb The number of bytes to convert.1113 *1114 * @note Rounds up the result.1115 */1116 uint64_t PDMAudioPropsBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)1117 {1118 AssertPtrReturn(pProps, 0);1119 1120 /* Check parameters to prevent division by chainsaw: */1121 uint32_t const uHz = pProps->uHz;1122 if (uHz)1123 {1124 const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);1125 if (cbFrame)1126 {1127 /* Round cb up to closest frame size: */1128 cb = (cb + cbFrame - 1) / cbFrame;1129 1130 /* Convert to nanoseconds. */1131 return (cb * (uint64_t)RT_NS_1SEC + uHz - 1) / uHz;1132 }1133 }1134 return 0;1135 }1136 1137 /**1138 * Converts frames to bytes.1139 *1140 * @returns Number of bytes.1141 * @param pProps The PCM properties to use.1142 * @param cFrames Number of audio frames to convert.1143 * @sa PDMAUDIOPCMPROPS_F2B1144 */1145 uint32_t PDMAudioPropsFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)1146 {1147 AssertPtrReturn(pProps, 0);1148 return PDMAUDIOPCMPROPS_F2B(pProps, cFrames);1149 }1150 1151 /**1152 * Converts frames to milliseconds.1153 *1154 * @returns milliseconds.1155 * @param pProps The PCM properties to use.1156 * @param cFrames Number of audio frames to convert.1157 * @note No rounding here, result is floored.1158 */1159 uint64_t PDMAudioPropsFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)1160 {1161 AssertPtrReturn(pProps, 0);1162 1163 /* Check input to prevent division by chainsaw: */1164 uint32_t const uHz = pProps->uHz;1165 if (uHz)1166 return ASMMultU32ByU32DivByU32(cFrames, RT_MS_1SEC, uHz);1167 return 0;1168 }1169 1170 /**1171 * Converts frames to nanoseconds.1172 *1173 * @returns Nanoseconds.1174 * @param pProps The PCM properties to use.1175 * @param cFrames Number of audio frames to convert.1176 * @note No rounding here, result is floored.1177 */1178 uint64_t PDMAudioPropsFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)1179 {1180 AssertPtrReturn(pProps, 0);1181 1182 /* Check input to prevent division by chainsaw: */1183 uint32_t const uHz = pProps->uHz;1184 if (uHz)1185 return ASMMultU32ByU32DivByU32(cFrames, RT_NS_1SEC, uHz);1186 return 0;1187 }1188 1189 /**1190 * Converts milliseconds to frames.1191 *1192 * @returns Number of frames1193 * @param pProps The PCM properties to use.1194 * @param cMs The number of milliseconds to convert.1195 *1196 * @note The result is rounded rather than floored (hysterical raisins).1197 */1198 uint32_t PDMAudioPropsMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)1199 {1200 AssertPtrReturn(pProps, 0);1201 1202 uint32_t const uHz = pProps->uHz;1203 uint32_t cFrames;1204 if (cMs < RT_MS_1SEC)1205 cFrames = 0;1206 else1207 {1208 cFrames = cMs / RT_MS_1SEC * uHz;1209 cMs %= RT_MS_1SEC;1210 }1211 cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cMs) + RT_MS_1SEC - 1) / RT_MS_1SEC;1212 return cFrames;1213 }1214 1215 /**1216 * Converts milliseconds to bytes.1217 *1218 * @returns Number of bytes (frame aligned).1219 * @param pProps The PCM properties to use.1220 * @param cMs The number of milliseconds to convert.1221 *1222 * @note The result is rounded rather than floored (hysterical raisins).1223 */1224 uint32_t PDMAudioPropsMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)1225 {1226 return PDMAUDIOPCMPROPS_F2B(pProps, PDMAudioPropsMilliToFrames(pProps, cMs));1227 }1228 1229 /**1230 * Converts nanoseconds to frames.1231 *1232 * @returns Number of frames1233 * @param pProps The PCM properties to use.1234 * @param cNs The number of nanoseconds to convert.1235 *1236 * @note The result is rounded rather than floored (hysterical raisins).1237 */1238 uint32_t PDMAudioPropsNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)1239 {1240 AssertPtrReturn(pProps, 0);1241 1242 uint32_t const uHz = pProps->uHz;1243 uint32_t cFrames;1244 if (cNs < RT_NS_1SEC)1245 cFrames = 0;1246 else1247 {1248 cFrames = cNs / RT_NS_1SEC * uHz;1249 cNs %= RT_NS_1SEC;1250 }1251 cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cNs) + RT_NS_1SEC - 1) / RT_NS_1SEC;1252 return cFrames;1253 }1254 1255 /**1256 * Converts nanoseconds to bytes.1257 *1258 * @returns Number of bytes (frame aligned).1259 * @param pProps The PCM properties to use.1260 * @param cNs The number of nanoseconds to convert.1261 *1262 * @note The result is rounded rather than floored (hysterical raisins).1263 */1264 uint32_t PDMAudioPropsNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)1265 {1266 return PDMAUDIOPCMPROPS_F2B(pProps, PDMAudioPropsNanoToFrames(pProps, cNs));1267 }1268 1269 /**1270 * Clears a sample buffer by the given amount of audio frames with silence (according to the format1271 * given by the PCM properties).1272 *1273 * @param pProps The PCM properties to apply.1274 * @param pvBuf The buffer to clear.1275 * @param cbBuf The buffer size in bytes.1276 * @param cFrames The number of audio frames to clear. Capped at @a cbBuf1277 * if exceeding the buffer. If the size is an unaligned1278 * number of frames, the extra bytes may be left1279 * uninitialized in some configurations.1280 */1281 void PDMAudioPropsClearBuffer(PCPDMAUDIOPCMPROPS pProps, void *pvBuf, size_t cbBuf, uint32_t cFrames)1282 {1283 /*1284 * Validate input1285 */1286 AssertPtrReturnVoid(pProps);1287 Assert(pProps->cbSample);1288 if (!cbBuf || !cFrames)1289 return;1290 AssertPtrReturnVoid(pvBuf);1291 1292 Assert(pProps->fSwapEndian == false); /** @todo Swapping Endianness is not supported yet. */1293 1294 /*1295 * Decide how much needs clearing.1296 */1297 size_t cbToClear = PDMAudioPropsFramesToBytes(pProps, cFrames);1298 AssertStmt(cbToClear <= cbBuf, cbToClear = cbBuf);1299 1300 Log2Func(("pProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cBytes=%RU8\n",1301 pProps, pvBuf, cFrames, pProps->fSigned, pProps->cbSample));1302 1303 /*1304 * Do the job.1305 */1306 if (pProps->fSigned)1307 RT_BZERO(pvBuf, cbToClear);1308 else /* Unsigned formats. */1309 {1310 switch (pProps->cbSample)1311 {1312 case 1: /* 8 bit */1313 memset(pvBuf, 0x80, cbToClear);1314 break;1315 1316 case 2: /* 16 bit */1317 {1318 uint16_t *pu16Dst = (uint16_t *)pvBuf;1319 size_t cLeft = cbToClear / sizeof(uint16_t);1320 while (cLeft-- > 0)1321 *pu16Dst++ = 0x80;1322 break;1323 }1324 1325 /** @todo Add 24 bit? */1326 1327 case 4: /* 32 bit */1328 ASMMemFill32(pvBuf, cbToClear & ~(size_t)3, 0x80);1329 break;1330 1331 default:1332 AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pProps->cbSample));1333 }1334 }1335 }1336 1337 /**1338 * Compares two sets of PCM properties.1339 *1340 * @returns @c true if the same, @c false if not.1341 * @param pProps1 The first set of properties to compare.1342 * @param pProps2 The second set of properties to compare.1343 */1344 bool PDMAudioPropsAreEqual(PCPDMAUDIOPCMPROPS pProps1, PCPDMAUDIOPCMPROPS pProps2)1345 {1346 AssertPtrReturn(pProps1, false);1347 AssertPtrReturn(pProps2, false);1348 1349 if (pProps1 == pProps2) /* If the pointers match, take a shortcut. */1350 return true;1351 1352 return pProps1->uHz == pProps2->uHz1353 && pProps1->cChannels == pProps2->cChannels1354 && pProps1->cbSample == pProps2->cbSample1355 && pProps1->fSigned == pProps2->fSigned1356 && pProps1->fSwapEndian == pProps2->fSwapEndian;1357 }1358 1359 596 /** 1360 597 * Checks whether given PCM properties are valid or not. … … 1372 609 { 1373 610 AssertPtrReturn(pProps, false); 611 612 AssertReturn(PDMAudioPropsAreValid(pProps), false); 1374 613 1375 614 /** @todo r=bird: This code is cannot make up its mind whether to return on … … 1412 651 1413 652 return fValid; 1414 }1415 1416 /**1417 * Get number of bytes per frame.1418 *1419 * @returns Number of bytes per audio frame.1420 * @param pProps PCM properties to use.1421 * @sa PDMAUDIOPCMPROPS_F2B1422 */1423 uint32_t PDMAudioPropsBytesPerFrame(PCPDMAUDIOPCMPROPS pProps)1424 {1425 return PDMAUDIOPCMPROPS_F2B(pProps, 1 /*cFrames*/);1426 }1427 1428 /**1429 * Prints PCM properties to the debug log.1430 *1431 * @param pProps Stream configuration to log.1432 */1433 void PDMAudioPropsLog(PCPDMAUDIOPCMPROPS pProps)1434 {1435 AssertPtrReturnVoid(pProps);1436 1437 Log(("uHz=%RU32, cChannels=%RU8, cBits=%RU8%s",1438 pProps->uHz, pProps->cChannels, pProps->cbSample * 8, pProps->fSigned ? "S" : "U"));1439 653 } 1440 654 -
trunk/src/VBox/Devices/Audio/DrvHostALSAAudio.cpp
r88023 r88028 50 50 #include <iprt/uuid.h> /* For PDMIBASE_2_PDMDRV. */ 51 51 #include <VBox/vmm/pdmaudioifs.h> 52 #include <VBox/vmm/pdmaudioinline.h> 52 53 53 54 RT_C_DECLS_BEGIN 54 #include "alsa_stubs.h"55 #include "alsa_mangling.h"55 # include "alsa_stubs.h" 56 # include "alsa_mangling.h" 56 57 RT_C_DECLS_END 57 58 -
trunk/src/VBox/Devices/Audio/DrvHostCoreAudio.cpp
r88026 r88028 22 22 #define LOG_GROUP LOG_GROUP_DRV_HOST_AUDIO 23 23 #include <VBox/log.h> 24 #include <VBox/vmm/pdmaudioinline.h> 24 25 25 26 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/DrvHostDSound.cpp
r88027 r88028 29 29 #include <iprt/uuid.h> 30 30 #include <iprt/utf16.h> 31 32 #include <VBox/vmm/pdmaudioinline.h> 31 33 32 34 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/DrvHostDebugAudio.cpp
r88023 r88028 27 27 #include <VBox/log.h> 28 28 #include <VBox/vmm/pdmaudioifs.h> 29 #include <VBox/vmm/pdmaudioinline.h> 29 30 30 31 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/DrvHostNullAudio.cpp
r88023 r88028 53 53 #include <VBox/log.h> 54 54 #include <VBox/vmm/pdmaudioifs.h> 55 #include <VBox/vmm/pdmaudioinline.h> 55 56 56 57 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/DrvHostOSSAudio.cpp
r88023 r88028 29 29 #include <VBox/log.h> 30 30 #include <VBox/vmm/pdmaudioifs.h> 31 #include <VBox/vmm/pdmaudioinline.h> 31 32 32 33 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/DrvHostPulseAudio.cpp
r88027 r88028 23 23 #include <VBox/log.h> 24 24 #include <VBox/vmm/pdmaudioifs.h> 25 #include <VBox/vmm/pdmaudioinline.h> 25 26 26 27 #include <stdio.h> … … 32 33 33 34 RT_C_DECLS_BEGIN 34 #include "pulse_mangling.h"35 #include "pulse_stubs.h"35 # include "pulse_mangling.h" 36 # include "pulse_stubs.h" 36 37 RT_C_DECLS_END 37 38 -
trunk/src/VBox/Devices/Audio/DrvHostValidationKit.cpp
r88023 r88028 23 23 #include <VBox/log.h> 24 24 #include <VBox/vmm/pdmaudioifs.h> 25 #include <VBox/vmm/pdmaudioinline.h> 25 26 26 27 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/HDACodec.cpp
r88027 r88028 29 29 #include <VBox/vmm/pdmdev.h> 30 30 #include <VBox/vmm/pdmaudioifs.h> 31 #include <VBox/vmm/pdmaudioinline.h> 31 32 32 33 #include <iprt/assert.h> -
trunk/src/VBox/Devices/Audio/HDAStream.cpp
r88022 r88028 29 29 #include <VBox/vmm/pdmdev.h> 30 30 #include <VBox/vmm/pdmaudioifs.h> 31 #include <VBox/vmm/pdmaudioinline.h> 31 32 32 33 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/HDAStreamMap.cpp
r88016 r88028 27 27 #include <VBox/vmm/pdmdev.h> 28 28 #include <VBox/vmm/pdmaudioifs.h> 29 #include <VBox/vmm/pdmaudioinline.h> 29 30 30 31 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/HDAStreamPeriod.cpp
r88016 r88028 35 35 #include <VBox/vmm/pdmdev.h> 36 36 #include <VBox/vmm/pdmaudioifs.h> 37 #include <VBox/vmm/pdmaudioinline.h> 37 38 38 39 #include "DrvAudio.h" -
trunk/src/VBox/Devices/Audio/testcase/tstAudioMixBuffer.cpp
r88022 r88028 28 28 #include <iprt/test.h> 29 29 30 #include <VBox/vmm/pdmaudioinline.h> 30 31 31 32 #include "../AudioMixBuffer.h" -
trunk/src/VBox/Main/Makefile.kmk
r88021 r88028 1035 1035 # Audio bits. 1036 1036 VBoxC_SOURCES += \ 1037 ../Devices/Audio/DrvAudioCommon.cpp \1038 1037 src-client/AudioDriver.cpp \ 1039 1038 $(if $(VBOX_WITH_AUDIO_VRDE),src-client/DrvAudioVRDE.cpp,) -
trunk/src/VBox/Main/src-client/DrvAudioRec.cpp
r88023 r88028 89 89 #include "ConsoleImpl.h" 90 90 91 #include "../../Devices/Audio/DrvAudio.h" /* Ugly! */92 91 #include "WebMWriter.h" 93 92 … … 95 94 #include <iprt/cdefs.h> 96 95 96 #include <VBox/vmm/cfgm.h> 97 #include <VBox/vmm/pdmdrv.h> 97 98 #include <VBox/vmm/pdmaudioifs.h> 98 #include <VBox/vmm/pdmdrv.h> 99 #include <VBox/vmm/cfgm.h> 99 #include <VBox/vmm/pdmaudioinline.h> 100 100 #include <VBox/err.h> 101 101 … … 1232 1232 pPCMProps->fSwapEndian = false; 1233 1233 1234 AssertMsgReturn( DrvAudioHlpPcmPropsAreValid(pPCMProps),1234 AssertMsgReturn(PDMAudioPropsAreValid(pPCMProps), 1235 1235 ("Configuration error: Audio configuration is invalid!\n"), VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES); 1236 1236 -
trunk/src/VBox/Main/src-client/DrvAudioVRDE.cpp
r88023 r88028 28 28 #include "ConsoleVRDPServer.h" 29 29 30 #include "../../Devices/Audio/DrvAudio.h"31 32 30 #include <iprt/mem.h> 33 31 #include <iprt/cdefs.h> 34 32 #include <iprt/circbuf.h> 35 33 34 #include <VBox/vmm/cfgm.h> 35 #include <VBox/vmm/pdmdrv.h> 36 36 #include <VBox/vmm/pdmaudioifs.h> 37 #include <VBox/vmm/pdm drv.h>37 #include <VBox/vmm/pdmaudioinline.h> 38 38 #include <VBox/RemoteDesktop/VRDE.h> 39 #include <VBox/vmm/cfgm.h>40 39 #include <VBox/err.h> 41 40
Note:
See TracChangeset
for help on using the changeset viewer.