VirtualBox

Changeset 88008 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Mar 8, 2021 12:31:30 PM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143136
Message:

Audio: Moved the PCM property helpers closer together. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvAudioCommon.cpp

    r88007 r88008  
    113113            case 32: return PDMAUDIOFMT_U32;
    114114            default: AssertMsgFailedReturn(("Bogus audio bits %RU8\n", cBits), PDMAUDIOFMT_INVALID);
    115         }
    116     }
    117 }
    118 
    119 /**
    120  * Clears a sample buffer by the given amount of audio frames with silence (according to the format
    121  * given by the PCM properties).
    122  *
    123  * @param   pPCMProps               PCM properties to use for the buffer to clear.
    124  * @param   pvBuf                   Buffer to clear.
    125  * @param   cbBuf                   Size (in bytes) of the buffer.
    126  * @param   cFrames                 Number of audio frames to clear in the buffer.
    127  */
    128 void DrvAudioHlpClearBuf(PCPDMAUDIOPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cFrames)
    129 {
    130     /*
    131      * Validate input
    132      */
    133     AssertPtrReturnVoid(pPCMProps);
    134     Assert(pPCMProps->cbSample);
    135     if (!cbBuf || !cFrames)
    136         return;
    137     AssertPtrReturnVoid(pvBuf);
    138 
    139     Assert(pPCMProps->fSwapEndian == false); /** @todo Swapping Endianness is not supported yet. */
    140 
    141     /*
    142      * Decide how much needs clearing.
    143      */
    144     size_t cbToClear = DrvAudioHlpFramesToBytes(pPCMProps, cFrames);
    145     AssertStmt(cbToClear <= cbBuf, cbToClear = cbBuf);
    146 
    147     Log2Func(("pPCMProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cBytes=%RU8\n",
    148               pPCMProps, pvBuf, cFrames, pPCMProps->fSigned, pPCMProps->cbSample));
    149 
    150     /*
    151      * Do the job.
    152      */
    153     if (pPCMProps->fSigned)
    154         RT_BZERO(pvBuf, cbToClear);
    155     else /* Unsigned formats. */
    156     {
    157         switch (pPCMProps->cbSample)
    158         {
    159             case 1: /* 8 bit */
    160                 memset(pvBuf, 0x80, cbToClear);
    161                 break;
    162 
    163             case 2: /* 16 bit */
    164             {
    165                 uint16_t *pu16Dst = (uint16_t *)pvBuf;
    166                 size_t    cLeft   = cbToClear / sizeof(uint16_t);
    167                 while (cLeft-- > 0)
    168                     *pu16Dst++ = 0x80;
    169                 break;
    170             }
    171 
    172             /** @todo Add 24 bit? */
    173 
    174             case 4: /* 32 bit */
    175                 ASMMemFill32(pvBuf, cbToClear & ~(size_t)3, 0x80);
    176                 break;
    177 
    178             default:
    179                 AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pPCMProps->cbSample));
    180115        }
    181116    }
     
    800735    AssertMsgFailed(("Invalid audio format '%s'\n", pszFmt));
    801736    return PDMAUDIOFMT_INVALID;
     737}
     738
     739/**
     740 * Initializes a stream configuration with its default values.
     741 *
     742 * @param   pCfg                Stream configuration to initialize.
     743 */
     744void DrvAudioHlpStreamCfgInit(PPDMAUDIOSTREAMCFG pCfg)
     745{
     746    AssertPtrReturnVoid(pCfg);
     747
     748    RT_ZERO(*pCfg);
     749
     750    pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */
     751}
     752
     753/**
     754 * Checks whether a given stream configuration is valid or not.
     755 *
     756 * Returns @c true if configuration is valid, @c false if not.
     757 * @param   pCfg                Stream configuration to check.
     758 */
     759bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg)
     760{
     761    AssertPtrReturn(pCfg, false);
     762
     763    bool fValid = (   pCfg->enmDir == PDMAUDIODIR_IN
     764                   || pCfg->enmDir == PDMAUDIODIR_OUT);
     765
     766    fValid &= (   pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED
     767               || pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
     768
     769    if (fValid)
     770        fValid = DrvAudioHlpPCMPropsAreValid(&pCfg->Props);
     771
     772    return fValid;
     773}
     774
     775/**
     776 * Frees an allocated audio stream configuration.
     777 *
     778 * @param   pCfg                Audio stream configuration to free.
     779 */
     780void DrvAudioHlpStreamCfgFree(PPDMAUDIOSTREAMCFG pCfg)
     781{
     782    if (pCfg)
     783    {
     784        RTMemFree(pCfg);
     785        pCfg = NULL;
     786    }
     787}
     788
     789/**
     790 * Copies a source stream configuration to a destination stream configuration.
     791 *
     792 * @returns IPRT status code.
     793 * @param   pDstCfg             Destination stream configuration to copy source to.
     794 * @param   pSrcCfg             Source stream configuration to copy to destination.
     795 */
     796int DrvAudioHlpStreamCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg)
     797{
     798    AssertPtrReturn(pDstCfg, VERR_INVALID_POINTER);
     799    AssertPtrReturn(pSrcCfg, VERR_INVALID_POINTER);
     800
     801#ifdef VBOX_STRICT
     802    if (!DrvAudioHlpStreamCfgIsValid(pSrcCfg))
     803    {
     804        AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pSrcCfg->szName, pSrcCfg));
     805        return VERR_INVALID_PARAMETER;
     806    }
     807#endif
     808
     809    memcpy(pDstCfg, pSrcCfg, sizeof(PDMAUDIOSTREAMCFG));
     810
     811    return VINF_SUCCESS;
     812}
     813
     814/**
     815 * Duplicates an audio stream configuration.
     816 * Must be free'd with DrvAudioHlpStreamCfgFree().
     817 *
     818 * @return  Duplicates audio stream configuration on success, or NULL on failure.
     819 * @param   pCfg                    Audio stream configuration to duplicate.
     820 */
     821PPDMAUDIOSTREAMCFG DrvAudioHlpStreamCfgDup(PCPDMAUDIOSTREAMCFG pCfg)
     822{
     823    AssertPtrReturn(pCfg, NULL);
     824
     825#ifdef VBOX_STRICT
     826    if (!DrvAudioHlpStreamCfgIsValid(pCfg))
     827    {
     828        AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pCfg->szName, pCfg));
     829        return NULL;
     830    }
     831#endif
     832
     833    PPDMAUDIOSTREAMCFG pDst = (PPDMAUDIOSTREAMCFG)RTMemAllocZ(sizeof(PDMAUDIOSTREAMCFG));
     834    if (!pDst)
     835        return NULL;
     836
     837    int rc2 = DrvAudioHlpStreamCfgCopy(pDst, pCfg);
     838    if (RT_FAILURE(rc2))
     839    {
     840        DrvAudioHlpStreamCfgFree(pDst);
     841        pDst = NULL;
     842    }
     843
     844    AssertPtr(pDst);
     845    return pDst;
     846}
     847
     848/**
     849 * Prints an audio stream configuration to the debug log.
     850 *
     851 * @param   pCfg                Stream configuration to log.
     852 */
     853void DrvAudioHlpStreamCfgPrint(PCPDMAUDIOSTREAMCFG pCfg)
     854{
     855    if (!pCfg)
     856        return;
     857
     858    LogFunc(("szName=%s, enmDir=%RU32 (uHz=%RU32, cBits=%RU8%s, cChannels=%RU8)\n",
     859             pCfg->szName, pCfg->enmDir,
     860             pCfg->Props.uHz, pCfg->Props.cbSample * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannels));
     861}
     862
     863/**
     864 * Converts a stream command to a string.
     865 *
     866 * @returns Stringified stream command, or "Unknown", if not found.
     867 * @param   enmCmd              Stream command to convert.
     868 */
     869const char *DrvAudioHlpStreamCmdToStr(PDMAUDIOSTREAMCMD enmCmd)
     870{
     871    switch (enmCmd)
     872    {
     873        case PDMAUDIOSTREAMCMD_INVALID: return "Invalid";
     874        case PDMAUDIOSTREAMCMD_UNKNOWN: return "Unknown";
     875        case PDMAUDIOSTREAMCMD_ENABLE:  return "Enable";
     876        case PDMAUDIOSTREAMCMD_DISABLE: return "Disable";
     877        case PDMAUDIOSTREAMCMD_PAUSE:   return "Pause";
     878        case PDMAUDIOSTREAMCMD_RESUME:  return "Resume";
     879        case PDMAUDIOSTREAMCMD_DRAIN:   return "Drain";
     880        case PDMAUDIOSTREAMCMD_DROP:    return "Drop";
     881        case PDMAUDIOSTREAMCMD_32BIT_HACK:
     882            break;
     883    }
     884    AssertMsgFailed(("Invalid stream command %d\n", enmCmd));
     885    return "Unknown";
     886}
     887
     888/**
     889 * Returns @c true if the given stream status indicates a can-be-read-from stream,
     890 * @c false if not.
     891 *
     892 * @returns @c true if ready to be read from, @c if not.
     893 * @param   fStatus     Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX.
     894 */
     895bool DrvAudioHlpStreamStatusCanRead(PDMAUDIOSTREAMSTS fStatus)
     896{
     897    AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);
     898
     899    return      fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED
     900           &&   fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED
     901           && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
     902           && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);
     903}
     904
     905/**
     906 * Returns @c true if the given stream status indicates a can-be-written-to stream,
     907 * @c false if not.
     908 *
     909 * @returns @c true if ready to be written to, @c if not.
     910 * @param   fStatus     Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX.
     911 */
     912bool DrvAudioHlpStreamStatusCanWrite(PDMAUDIOSTREAMSTS fStatus)
     913{
     914    AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);
     915
     916    return      fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED
     917           &&   fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED
     918           && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
     919           && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
     920           && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);
     921}
     922
     923/**
     924 * Returns @c true if the given stream status indicates a ready-to-operate stream,
     925 * @c false if not.
     926 *
     927 * @returns @c true if ready to operate, @c if not.
     928 * @param   fStatus Stream status to evaluate.
     929 */
     930bool DrvAudioHlpStreamStatusIsReady(PDMAUDIOSTREAMSTS fStatus)
     931{
     932    AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);
     933
     934    return      fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED
     935           &&   fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED
     936           && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);
     937}
     938
     939/**
     940 * Calculates the audio bit rate of the given bits per sample, the Hz and the number
     941 * of audio channels.
     942 *
     943 * Divide the result by 8 to get the byte rate.
     944 *
     945 * @returns Bitrate.
     946 * @param   cBits               Number of bits per sample.
     947 * @param   uHz                 Hz (Hertz) rate.
     948 * @param   cChannels           Number of audio channels.
     949 */
     950uint32_t DrvAudioHlpCalcBitrate(uint8_t cBits, uint32_t uHz, uint8_t cChannels)
     951{
     952    return cBits * uHz * cChannels;
     953}
     954
     955
     956/*********************************************************************************************************************************
     957*   PCM Property Helpers                                                                                                         *
     958*********************************************************************************************************************************/
     959
     960/**
     961 * Gets the bitrate.
     962 *
     963 * Divide the result by 8 to get the byte rate.
     964 *
     965 * @returns Bit rate.
     966 * @param   pProps              PCM properties to calculate bitrate for.
     967 */
     968uint32_t DrvAudioHlpGetBitrate(PCPDMAUDIOPCMPROPS pProps)
     969{
     970    return DrvAudioHlpCalcBitrate(pProps->cbSample * 8, pProps->uHz, pProps->cChannels);
     971}
     972
     973/**
     974 * Rounds down the given byte amount to the nearest frame boundrary.
     975 *
     976 * @returns Rounded byte amount.
     977 * @param   pProps      PCM properties to use.
     978 * @param   cb          The size (in bytes) to round.
     979 */
     980uint32_t DrvAudioHlpFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
     981{
     982    AssertPtrReturn(pProps, 0);
     983    return PDMAUDIOPCMPROPS_F2B(pProps, PDMAUDIOPCMPROPS_B2F(pProps, cb));
     984}
     985
     986/**
     987 * Checks if the given size is aligned on a frame boundrary.
     988 *
     989 * @returns @c true if properly aligned, @c false if not.
     990 * @param   pProps      PCM properties to use.
     991 * @param   cb          The size (in bytes) to check.
     992 */
     993bool DrvAudioHlpIsBytesAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
     994{
     995    AssertPtrReturn(pProps, false);
     996    uint32_t const cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
     997    AssertReturn(cbFrame, false);
     998    return cb % cbFrame == 0;
     999}
     1000
     1001/**
     1002 * Returns the bytes per second for given PCM properties.
     1003 *
     1004 * @returns Bytes per second.
     1005 * @param   pProps              PCM properties to retrieve size for.
     1006 */
     1007DECLINLINE(uint64_t) drvAudioHlpBytesPerSec(PCPDMAUDIOPCMPROPS pProps)
     1008{
     1009    return PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */) * pProps->uHz;
     1010}
     1011
     1012/**
     1013 * Converts bytes to frames (rounding down of course).
     1014 *
     1015 * @returns Number of frames.
     1016 * @param   pProps      PCM properties to use.
     1017 * @param   cb          The number of bytes to convert.
     1018 */
     1019uint32_t DrvAudioHlpBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
     1020{
     1021    AssertPtrReturn(pProps, 0);
     1022    return PDMAUDIOPCMPROPS_B2F(pProps, cb);
     1023}
     1024
     1025/**
     1026 * Converts bytes to milliseconds.
     1027 *
     1028 * @return  Number milliseconds @a cb takes to play or record.
     1029 * @param   pProps      PCM properties to use.
     1030 * @param   cb          The number of bytes to convert.
     1031 *
     1032 * @note    Rounds up the result.
     1033 */
     1034uint64_t DrvAudioHlpBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
     1035{
     1036    AssertPtrReturn(pProps, 0);
     1037
     1038    /* Check parameters to prevent division by chainsaw: */
     1039    uint32_t const uHz = pProps->uHz;
     1040    if (uHz)
     1041    {
     1042        const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
     1043        if (cbFrame)
     1044        {
     1045            /* Round cb up to closest frame size: */
     1046            cb = (cb + cbFrame - 1) / cbFrame;
     1047
     1048            /* Convert to milliseconds. */
     1049            return (cb * (uint64_t)RT_MS_1SEC + uHz - 1) / uHz;
     1050        }
     1051    }
     1052    return 0;
     1053}
     1054
     1055/**
     1056 * Converts bytes to microseconds.
     1057 *
     1058 * @return  Number microseconds @a cb takes to play or record.
     1059 * @param   pProps      PCM properties to use.
     1060 * @param   cb          The number of bytes to convert.
     1061 *
     1062 * @note    Rounds up the result.
     1063 */
     1064uint64_t DrvAudioHlpBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
     1065{
     1066    AssertPtrReturn(pProps, 0);
     1067
     1068    /* Check parameters to prevent division by chainsaw: */
     1069    uint32_t const uHz = pProps->uHz;
     1070    if (uHz)
     1071    {
     1072        const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
     1073        if (cbFrame)
     1074        {
     1075            /* Round cb up to closest frame size: */
     1076            cb = (cb + cbFrame - 1) / cbFrame;
     1077
     1078            /* Convert to microseconds. */
     1079            return (cb * (uint64_t)RT_US_1SEC + uHz - 1) / uHz;
     1080        }
     1081    }
     1082    return 0;
     1083}
     1084
     1085/**
     1086 * Converts bytes to nanoseconds.
     1087 *
     1088 * @return  Number nanoseconds @a cb takes to play or record.
     1089 * @param   pProps      PCM properties to use.
     1090 * @param   cb          The number of bytes to convert.
     1091 *
     1092 * @note    Rounds up the result.
     1093 */
     1094uint64_t DrvAudioHlpBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
     1095{
     1096    AssertPtrReturn(pProps, 0);
     1097
     1098    /* Check parameters to prevent division by chainsaw: */
     1099    uint32_t const uHz = pProps->uHz;
     1100    if (uHz)
     1101    {
     1102        const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
     1103        if (cbFrame)
     1104        {
     1105            /* Round cb up to closest frame size: */
     1106            cb = (cb + cbFrame - 1) / cbFrame;
     1107
     1108            /* Convert to nanoseconds. */
     1109            return (cb * (uint64_t)RT_NS_1SEC + uHz - 1) / uHz;
     1110        }
     1111    }
     1112    return 0;
     1113}
     1114
     1115/**
     1116 * Converts frames to bytes.
     1117 *
     1118 * @return Number of bytes.
     1119 * @param   pProps      The PCM properties to use.
     1120 * @param   cFrames     Number of audio frames to convert.
     1121 */
     1122uint32_t DrvAudioHlpFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
     1123{
     1124    AssertPtrReturn(pProps, 0);
     1125    return PDMAUDIOPCMPROPS_F2B(pProps, cFrames);
     1126}
     1127
     1128/**
     1129 * Converts frames to milliseconds.
     1130 *
     1131 * @returns milliseconds.
     1132 * @param   pProps      The PCM properties to use.
     1133 * @param   cFrames     Number of audio frames to convert.
     1134 * @note    No rounding here, result is floored.
     1135 */
     1136uint64_t DrvAudioHlpFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
     1137{
     1138    AssertPtrReturn(pProps, 0);
     1139
     1140    /* Check input to prevent division by chainsaw: */
     1141    uint32_t const uHz = pProps->uHz;
     1142    if (uHz)
     1143        return ASMMultU32ByU32DivByU32(cFrames, RT_MS_1SEC, uHz);
     1144    return 0;
     1145}
     1146
     1147/**
     1148 * Converts frames to nanoseconds.
     1149 *
     1150 * @returns Nanoseconds.
     1151 * @param   pProps      The PCM properties to use.
     1152 * @param   cFrames     Number of audio frames to convert.
     1153 * @note    No rounding here, result is floored.
     1154 */
     1155uint64_t DrvAudioHlpFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
     1156{
     1157    AssertPtrReturn(pProps, 0);
     1158
     1159    /* Check input to prevent division by chainsaw: */
     1160    uint32_t const uHz = pProps->uHz;
     1161    if (uHz)
     1162        return ASMMultU32ByU32DivByU32(cFrames, RT_NS_1SEC, uHz);
     1163    return 0;
     1164}
     1165
     1166/**
     1167 * Converts milliseconds to frames.
     1168 *
     1169 * @returns Number of frames
     1170 * @param   pProps      The PCM properties to use.
     1171 * @param   cMs         The number of milliseconds to convert.
     1172 *
     1173 * @note    The result is rounded rather than floored (hysterical raisins).
     1174 */
     1175uint32_t DrvAudioHlpMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)
     1176{
     1177    AssertPtrReturn(pProps, 0);
     1178
     1179    uint32_t const uHz = pProps->uHz;
     1180    uint32_t cFrames;
     1181    if (cMs < RT_MS_1SEC)
     1182        cFrames = 0;
     1183    else
     1184    {
     1185        cFrames = cMs / RT_MS_1SEC * uHz;
     1186        cMs %= RT_MS_1SEC;
     1187    }
     1188    cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cMs) + RT_MS_1SEC - 1) / RT_MS_1SEC;
     1189    return cFrames;
     1190}
     1191
     1192/**
     1193 * Converts milliseconds to bytes.
     1194 *
     1195 * @returns Number of bytes (frame aligned).
     1196 * @param   pProps      The PCM properties to use.
     1197 * @param   cMs         The number of milliseconds to convert.
     1198 *
     1199 * @note    The result is rounded rather than floored (hysterical raisins).
     1200 */
     1201uint32_t DrvAudioHlpMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)
     1202{
     1203    return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpMilliToFrames(pProps, cMs));
     1204}
     1205
     1206/**
     1207 * Converts nanoseconds to frames.
     1208 *
     1209 * @returns Number of frames
     1210 * @param   pProps      The PCM properties to use.
     1211 * @param   cNs         The number of nanoseconds to convert.
     1212 *
     1213 * @note    The result is rounded rather than floored (hysterical raisins).
     1214 */
     1215uint32_t DrvAudioHlpNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
     1216{
     1217    AssertPtrReturn(pProps, 0);
     1218
     1219    uint32_t const uHz = pProps->uHz;
     1220    uint32_t cFrames;
     1221    if (cNs < RT_NS_1SEC)
     1222        cFrames = 0;
     1223    else
     1224    {
     1225        cFrames = cNs / RT_NS_1SEC * uHz;
     1226        cNs %= RT_NS_1SEC;
     1227    }
     1228    cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cNs) + RT_NS_1SEC - 1) / RT_NS_1SEC;
     1229    return cFrames;
     1230}
     1231
     1232/**
     1233 * Converts nanoseconds to bytes.
     1234 *
     1235 * @returns Number of bytes (frame aligned).
     1236 * @param   pProps      The PCM properties to use.
     1237 * @param   cNs         The number of nanoseconds to convert.
     1238 *
     1239 * @note    The result is rounded rather than floored (hysterical raisins).
     1240 */
     1241uint32_t DrvAudioHlpNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
     1242{
     1243    return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpNanoToFrames(pProps, cNs));
     1244}
     1245
     1246/**
     1247 * Clears a sample buffer by the given amount of audio frames with silence (according to the format
     1248 * given by the PCM properties).
     1249 *
     1250 * @param   pPCMProps               PCM properties to use for the buffer to clear.
     1251 * @param   pvBuf                   Buffer to clear.
     1252 * @param   cbBuf                   Size (in bytes) of the buffer.
     1253 * @param   cFrames                 Number of audio frames to clear in the buffer.
     1254 */
     1255void DrvAudioHlpClearBuf(PCPDMAUDIOPCMPROPS pPCMProps, void *pvBuf, size_t cbBuf, uint32_t cFrames)
     1256{
     1257    /*
     1258     * Validate input
     1259     */
     1260    AssertPtrReturnVoid(pPCMProps);
     1261    Assert(pPCMProps->cbSample);
     1262    if (!cbBuf || !cFrames)
     1263        return;
     1264    AssertPtrReturnVoid(pvBuf);
     1265
     1266    Assert(pPCMProps->fSwapEndian == false); /** @todo Swapping Endianness is not supported yet. */
     1267
     1268    /*
     1269     * Decide how much needs clearing.
     1270     */
     1271    size_t cbToClear = DrvAudioHlpFramesToBytes(pPCMProps, cFrames);
     1272    AssertStmt(cbToClear <= cbBuf, cbToClear = cbBuf);
     1273
     1274    Log2Func(("pPCMProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cBytes=%RU8\n",
     1275              pPCMProps, pvBuf, cFrames, pPCMProps->fSigned, pPCMProps->cbSample));
     1276
     1277    /*
     1278     * Do the job.
     1279     */
     1280    if (pPCMProps->fSigned)
     1281        RT_BZERO(pvBuf, cbToClear);
     1282    else /* Unsigned formats. */
     1283    {
     1284        switch (pPCMProps->cbSample)
     1285        {
     1286            case 1: /* 8 bit */
     1287                memset(pvBuf, 0x80, cbToClear);
     1288                break;
     1289
     1290            case 2: /* 16 bit */
     1291            {
     1292                uint16_t *pu16Dst = (uint16_t *)pvBuf;
     1293                size_t    cLeft   = cbToClear / sizeof(uint16_t);
     1294                while (cLeft-- > 0)
     1295                    *pu16Dst++ = 0x80;
     1296                break;
     1297            }
     1298
     1299            /** @todo Add 24 bit? */
     1300
     1301            case 4: /* 32 bit */
     1302                ASMMemFill32(pvBuf, cbToClear & ~(size_t)3, 0x80);
     1303                break;
     1304
     1305            default:
     1306                AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pPCMProps->cbSample));
     1307        }
     1308    }
    8021309}
    8031310
     
    9171424 * @param   pProps              PCM properties to convert.
    9181425 * @param   pCfg                Stream configuration to store result into.
     1426 * @todo r=bird: Rename to DrvAudioHlpStreamCfgInitFromPCMProps.
    9191427 */
    9201428int DrvAudioHlpPCMPropsToStreamCfg(PCPDMAUDIOPCMPROPS pProps, PPDMAUDIOSTREAMCFG pCfg)
     
    9291437}
    9301438
    931 /**
    932  * Initializes a stream configuration with its default values.
    933  *
    934  * @param   pCfg                Stream configuration to initialize.
    935  */
    936 void DrvAudioHlpStreamCfgInit(PPDMAUDIOSTREAMCFG pCfg)
    937 {
    938     AssertPtrReturnVoid(pCfg);
    939 
    940     RT_ZERO(*pCfg);
    941 
    942     pCfg->Backend.cFramesPreBuffering = UINT32_MAX; /* Explicitly set to "undefined". */
    943 }
    944 
    945 /**
    946  * Checks whether a given stream configuration is valid or not.
    947  *
    948  * Returns @c true if configuration is valid, @c false if not.
    949  * @param   pCfg                Stream configuration to check.
    950  */
    951 bool DrvAudioHlpStreamCfgIsValid(PCPDMAUDIOSTREAMCFG pCfg)
    952 {
    953     AssertPtrReturn(pCfg, false);
    954 
    955     bool fValid = (   pCfg->enmDir == PDMAUDIODIR_IN
    956                    || pCfg->enmDir == PDMAUDIODIR_OUT);
    957 
    958     fValid &= (   pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED
    959                || pCfg->enmLayout == PDMAUDIOSTREAMLAYOUT_RAW);
    960 
    961     if (fValid)
    962         fValid = DrvAudioHlpPCMPropsAreValid(&pCfg->Props);
    963 
    964     return fValid;
    965 }
    966 
    967 /**
    968  * Frees an allocated audio stream configuration.
    969  *
    970  * @param   pCfg                Audio stream configuration to free.
    971  */
    972 void DrvAudioHlpStreamCfgFree(PPDMAUDIOSTREAMCFG pCfg)
    973 {
    974     if (pCfg)
    975     {
    976         RTMemFree(pCfg);
    977         pCfg = NULL;
    978     }
    979 }
    980 
    981 /**
    982  * Copies a source stream configuration to a destination stream configuration.
    983  *
    984  * @returns IPRT status code.
    985  * @param   pDstCfg             Destination stream configuration to copy source to.
    986  * @param   pSrcCfg             Source stream configuration to copy to destination.
    987  */
    988 int DrvAudioHlpStreamCfgCopy(PPDMAUDIOSTREAMCFG pDstCfg, PCPDMAUDIOSTREAMCFG pSrcCfg)
    989 {
    990     AssertPtrReturn(pDstCfg, VERR_INVALID_POINTER);
    991     AssertPtrReturn(pSrcCfg, VERR_INVALID_POINTER);
    992 
    993 #ifdef VBOX_STRICT
    994     if (!DrvAudioHlpStreamCfgIsValid(pSrcCfg))
    995     {
    996         AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pSrcCfg->szName, pSrcCfg));
    997         return VERR_INVALID_PARAMETER;
    998     }
    999 #endif
    1000 
    1001     memcpy(pDstCfg, pSrcCfg, sizeof(PDMAUDIOSTREAMCFG));
    1002 
    1003     return VINF_SUCCESS;
    1004 }
    1005 
    1006 /**
    1007  * Duplicates an audio stream configuration.
    1008  * Must be free'd with DrvAudioHlpStreamCfgFree().
    1009  *
    1010  * @return  Duplicates audio stream configuration on success, or NULL on failure.
    1011  * @param   pCfg                    Audio stream configuration to duplicate.
    1012  */
    1013 PPDMAUDIOSTREAMCFG DrvAudioHlpStreamCfgDup(PCPDMAUDIOSTREAMCFG pCfg)
    1014 {
    1015     AssertPtrReturn(pCfg, NULL);
    1016 
    1017 #ifdef VBOX_STRICT
    1018     if (!DrvAudioHlpStreamCfgIsValid(pCfg))
    1019     {
    1020         AssertMsgFailed(("Stream config '%s' (%p) is invalid\n", pCfg->szName, pCfg));
    1021         return NULL;
    1022     }
    1023 #endif
    1024 
    1025     PPDMAUDIOSTREAMCFG pDst = (PPDMAUDIOSTREAMCFG)RTMemAllocZ(sizeof(PDMAUDIOSTREAMCFG));
    1026     if (!pDst)
    1027         return NULL;
    1028 
    1029     int rc2 = DrvAudioHlpStreamCfgCopy(pDst, pCfg);
    1030     if (RT_FAILURE(rc2))
    1031     {
    1032         DrvAudioHlpStreamCfgFree(pDst);
    1033         pDst = NULL;
    1034     }
    1035 
    1036     AssertPtr(pDst);
    1037     return pDst;
    1038 }
    1039 
    1040 /**
    1041  * Prints an audio stream configuration to the debug log.
    1042  *
    1043  * @param   pCfg                Stream configuration to log.
    1044  */
    1045 void DrvAudioHlpStreamCfgPrint(PCPDMAUDIOSTREAMCFG pCfg)
    1046 {
    1047     if (!pCfg)
    1048         return;
    1049 
    1050     LogFunc(("szName=%s, enmDir=%RU32 (uHz=%RU32, cBits=%RU8%s, cChannels=%RU8)\n",
    1051              pCfg->szName, pCfg->enmDir,
    1052              pCfg->Props.uHz, pCfg->Props.cbSample * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannels));
    1053 }
    1054 
    1055 /**
    1056  * Converts a stream command to a string.
    1057  *
    1058  * @returns Stringified stream command, or "Unknown", if not found.
    1059  * @param   enmCmd              Stream command to convert.
    1060  */
    1061 const char *DrvAudioHlpStreamCmdToStr(PDMAUDIOSTREAMCMD enmCmd)
    1062 {
    1063     switch (enmCmd)
    1064     {
    1065         case PDMAUDIOSTREAMCMD_INVALID: return "Invalid";
    1066         case PDMAUDIOSTREAMCMD_UNKNOWN: return "Unknown";
    1067         case PDMAUDIOSTREAMCMD_ENABLE:  return "Enable";
    1068         case PDMAUDIOSTREAMCMD_DISABLE: return "Disable";
    1069         case PDMAUDIOSTREAMCMD_PAUSE:   return "Pause";
    1070         case PDMAUDIOSTREAMCMD_RESUME:  return "Resume";
    1071         case PDMAUDIOSTREAMCMD_DRAIN:   return "Drain";
    1072         case PDMAUDIOSTREAMCMD_DROP:    return "Drop";
    1073         case PDMAUDIOSTREAMCMD_32BIT_HACK:
    1074             break;
    1075     }
    1076     AssertMsgFailed(("Invalid stream command %d\n", enmCmd));
    1077     return "Unknown";
    1078 }
    1079 
    1080 /**
    1081  * Returns @c true if the given stream status indicates a can-be-read-from stream,
    1082  * @c false if not.
    1083  *
    1084  * @returns @c true if ready to be read from, @c if not.
    1085  * @param   fStatus     Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX.
    1086  */
    1087 bool DrvAudioHlpStreamStatusCanRead(PDMAUDIOSTREAMSTS fStatus)
    1088 {
    1089     AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);
    1090 
    1091     return      fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED
    1092            &&   fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED
    1093            && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
    1094            && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);
    1095 }
    1096 
    1097 /**
    1098  * Returns @c true if the given stream status indicates a can-be-written-to stream,
    1099  * @c false if not.
    1100  *
    1101  * @returns @c true if ready to be written to, @c if not.
    1102  * @param   fStatus     Stream status to evaluate, PDMAUDIOSTREAMSTS_FLAGS_XXX.
    1103  */
    1104 bool DrvAudioHlpStreamStatusCanWrite(PDMAUDIOSTREAMSTS fStatus)
    1105 {
    1106     AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);
    1107 
    1108     return      fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED
    1109            &&   fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED
    1110            && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PAUSED)
    1111            && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_DISABLE)
    1112            && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);
    1113 }
    1114 
    1115 /**
    1116  * Returns @c true if the given stream status indicates a ready-to-operate stream,
    1117  * @c false if not.
    1118  *
    1119  * @returns @c true if ready to operate, @c if not.
    1120  * @param   fStatus Stream status to evaluate.
    1121  */
    1122 bool DrvAudioHlpStreamStatusIsReady(PDMAUDIOSTREAMSTS fStatus)
    1123 {
    1124     AssertReturn(fStatus & PDMAUDIOSTREAMSTS_VALID_MASK, false);
    1125 
    1126     return      fStatus & PDMAUDIOSTREAMSTS_FLAGS_INITIALIZED
    1127            &&   fStatus & PDMAUDIOSTREAMSTS_FLAGS_ENABLED
    1128            && !(fStatus & PDMAUDIOSTREAMSTS_FLAGS_PENDING_REINIT);
    1129 }
    1130 
    1131 /**
    1132  * Calculates the audio bit rate of the given bits per sample, the Hz and the number
    1133  * of audio channels.
    1134  *
    1135  * Divide the result by 8 to get the byte rate.
    1136  *
    1137  * @returns Bitrate.
    1138  * @param   cBits               Number of bits per sample.
    1139  * @param   uHz                 Hz (Hertz) rate.
    1140  * @param   cChannels           Number of audio channels.
    1141  */
    1142 uint32_t DrvAudioHlpCalcBitrate(uint8_t cBits, uint32_t uHz, uint8_t cChannels)
    1143 {
    1144     return cBits * uHz * cChannels;
    1145 }
    1146 
    1147 /**
    1148  * Gets the bitrate.
    1149  *
    1150  * Divide the result by 8 to get the byte rate.
    1151  *
    1152  * @returns Bit rate.
    1153  * @param   pProps              PCM properties to calculate bitrate for.
    1154  */
    1155 uint32_t DrvAudioHlpGetBitrate(PCPDMAUDIOPCMPROPS pProps)
    1156 {
    1157     return DrvAudioHlpCalcBitrate(pProps->cbSample * 8, pProps->uHz, pProps->cChannels);
    1158 }
    1159 
    1160 /**
    1161  * Rounds down the given byte amount to the nearest frame boundrary.
    1162  *
    1163  * @returns Rounded byte amount.
    1164  * @param   pProps      PCM properties to use.
    1165  * @param   cb          The size (in bytes) to round.
    1166  */
    1167 uint32_t DrvAudioHlpFloorBytesToFrame(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
    1168 {
    1169     AssertPtrReturn(pProps, 0);
    1170     return PDMAUDIOPCMPROPS_F2B(pProps, PDMAUDIOPCMPROPS_B2F(pProps, cb));
    1171 }
    1172 
    1173 /**
    1174  * Checks if the given size is aligned on a frame boundrary.
    1175  *
    1176  * @returns @c true if properly aligned, @c false if not.
    1177  * @param   pProps      PCM properties to use.
    1178  * @param   cb          The size (in bytes) to check.
    1179  */
    1180 bool DrvAudioHlpIsBytesAligned(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
    1181 {
    1182     AssertPtrReturn(pProps, false);
    1183     uint32_t const cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
    1184     AssertReturn(cbFrame, false);
    1185     return cb % cbFrame == 0;
    1186 }
    1187 
    1188 /**
    1189  * Returns the bytes per second for given PCM properties.
    1190  *
    1191  * @returns Bytes per second.
    1192  * @param   pProps              PCM properties to retrieve size for.
    1193  */
    1194 DECLINLINE(uint64_t) drvAudioHlpBytesPerSec(PCPDMAUDIOPCMPROPS pProps)
    1195 {
    1196     return PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */) * pProps->uHz;
    1197 }
    1198 
    1199 /**
    1200  * Converts bytes to frames (rounding down of course).
    1201  *
    1202  * @returns Number of frames.
    1203  * @param   pProps      PCM properties to use.
    1204  * @param   cb          The number of bytes to convert.
    1205  */
    1206 uint32_t DrvAudioHlpBytesToFrames(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
    1207 {
    1208     AssertPtrReturn(pProps, 0);
    1209     return PDMAUDIOPCMPROPS_B2F(pProps, cb);
    1210 }
    1211 
    1212 /**
    1213  * Converts bytes to milliseconds.
    1214  *
    1215  * @return  Number milliseconds @a cb takes to play or record.
    1216  * @param   pProps      PCM properties to use.
    1217  * @param   cb          The number of bytes to convert.
    1218  *
    1219  * @note    Rounds up the result.
    1220  */
    1221 uint64_t DrvAudioHlpBytesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
    1222 {
    1223     AssertPtrReturn(pProps, 0);
    1224 
    1225     /* Check parameters to prevent division by chainsaw: */
    1226     uint32_t const uHz = pProps->uHz;
    1227     if (uHz)
    1228     {
    1229         const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
    1230         if (cbFrame)
    1231         {
    1232             /* Round cb up to closest frame size: */
    1233             cb = (cb + cbFrame - 1) / cbFrame;
    1234 
    1235             /* Convert to milliseconds. */
    1236             return (cb * (uint64_t)RT_MS_1SEC + uHz - 1) / uHz;
    1237         }
    1238     }
    1239     return 0;
    1240 }
    1241 
    1242 /**
    1243  * Converts bytes to microseconds.
    1244  *
    1245  * @return  Number microseconds @a cb takes to play or record.
    1246  * @param   pProps      PCM properties to use.
    1247  * @param   cb          The number of bytes to convert.
    1248  *
    1249  * @note    Rounds up the result.
    1250  */
    1251 uint64_t DrvAudioHlpBytesToMicro(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
    1252 {
    1253     AssertPtrReturn(pProps, 0);
    1254 
    1255     /* Check parameters to prevent division by chainsaw: */
    1256     uint32_t const uHz = pProps->uHz;
    1257     if (uHz)
    1258     {
    1259         const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
    1260         if (cbFrame)
    1261         {
    1262             /* Round cb up to closest frame size: */
    1263             cb = (cb + cbFrame - 1) / cbFrame;
    1264 
    1265             /* Convert to microseconds. */
    1266             return (cb * (uint64_t)RT_US_1SEC + uHz - 1) / uHz;
    1267         }
    1268     }
    1269     return 0;
    1270 }
    1271 
    1272 /**
    1273  * Converts bytes to nanoseconds.
    1274  *
    1275  * @return  Number nanoseconds @a cb takes to play or record.
    1276  * @param   pProps      PCM properties to use.
    1277  * @param   cb          The number of bytes to convert.
    1278  *
    1279  * @note    Rounds up the result.
    1280  */
    1281 uint64_t DrvAudioHlpBytesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cb)
    1282 {
    1283     AssertPtrReturn(pProps, 0);
    1284 
    1285     /* Check parameters to prevent division by chainsaw: */
    1286     uint32_t const uHz = pProps->uHz;
    1287     if (uHz)
    1288     {
    1289         const unsigned cbFrame = PDMAUDIOPCMPROPS_F2B(pProps, 1 /* Frame */);
    1290         if (cbFrame)
    1291         {
    1292             /* Round cb up to closest frame size: */
    1293             cb = (cb + cbFrame - 1) / cbFrame;
    1294 
    1295             /* Convert to nanoseconds. */
    1296             return (cb * (uint64_t)RT_NS_1SEC + uHz - 1) / uHz;
    1297         }
    1298     }
    1299     return 0;
    1300 }
    1301 
    1302 /**
    1303  * Converts frames to bytes.
    1304  *
    1305  * @return Number of bytes.
    1306  * @param   pProps      The PCM properties to use.
    1307  * @param   cFrames     Number of audio frames to convert.
    1308  */
    1309 uint32_t DrvAudioHlpFramesToBytes(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
    1310 {
    1311     AssertPtrReturn(pProps, 0);
    1312     return PDMAUDIOPCMPROPS_F2B(pProps, cFrames);
    1313 }
    1314 
    1315 /**
    1316  * Converts frames to milliseconds.
    1317  *
    1318  * @returns milliseconds.
    1319  * @param   pProps      The PCM properties to use.
    1320  * @param   cFrames     Number of audio frames to convert.
    1321  * @note    No rounding here, result is floored.
    1322  */
    1323 uint64_t DrvAudioHlpFramesToMilli(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
    1324 {
    1325     AssertPtrReturn(pProps, 0);
    1326 
    1327     /* Check input to prevent division by chainsaw: */
    1328     uint32_t const uHz = pProps->uHz;
    1329     if (uHz)
    1330         return ASMMultU32ByU32DivByU32(cFrames, RT_MS_1SEC, uHz);
    1331     return 0;
    1332 }
    1333 
    1334 /**
    1335  * Converts frames to nanoseconds.
    1336  *
    1337  * @returns Nanoseconds.
    1338  * @param   pProps      The PCM properties to use.
    1339  * @param   cFrames     Number of audio frames to convert.
    1340  * @note    No rounding here, result is floored.
    1341  */
    1342 uint64_t DrvAudioHlpFramesToNano(PCPDMAUDIOPCMPROPS pProps, uint32_t cFrames)
    1343 {
    1344     AssertPtrReturn(pProps, 0);
    1345 
    1346     /* Check input to prevent division by chainsaw: */
    1347     uint32_t const uHz = pProps->uHz;
    1348     if (uHz)
    1349         return ASMMultU32ByU32DivByU32(cFrames, RT_NS_1SEC, uHz);
    1350     return 0;
    1351 }
    1352 
    1353 /**
    1354  * Converts milliseconds to frames.
    1355  *
    1356  * @returns Number of frames
    1357  * @param   pProps      The PCM properties to use.
    1358  * @param   cMs         The number of milliseconds to convert.
    1359  *
    1360  * @note    The result is rounded rather than floored (hysterical raisins).
    1361  */
    1362 uint32_t DrvAudioHlpMilliToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)
    1363 {
    1364     AssertPtrReturn(pProps, 0);
    1365 
    1366     uint32_t const uHz = pProps->uHz;
    1367     uint32_t cFrames;
    1368     if (cMs < RT_MS_1SEC)
    1369         cFrames = 0;
    1370     else
    1371     {
    1372         cFrames = cMs / RT_MS_1SEC * uHz;
    1373         cMs %= RT_MS_1SEC;
    1374     }
    1375     cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cMs) + RT_MS_1SEC - 1) / RT_MS_1SEC;
    1376     return cFrames;
    1377 }
    1378 
    1379 /**
    1380  * Converts milliseconds to bytes.
    1381  *
    1382  * @returns Number of bytes (frame aligned).
    1383  * @param   pProps      The PCM properties to use.
    1384  * @param   cMs         The number of milliseconds to convert.
    1385  *
    1386  * @note    The result is rounded rather than floored (hysterical raisins).
    1387  */
    1388 uint32_t DrvAudioHlpMilliToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cMs)
    1389 {
    1390     return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpMilliToFrames(pProps, cMs));
    1391 }
    1392 
    1393 /**
    1394  * Converts nanoseconds to frames.
    1395  *
    1396  * @returns Number of frames
    1397  * @param   pProps      The PCM properties to use.
    1398  * @param   cNs         The number of nanoseconds to convert.
    1399  *
    1400  * @note    The result is rounded rather than floored (hysterical raisins).
    1401  */
    1402 uint32_t DrvAudioHlpNanoToFrames(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
    1403 {
    1404     AssertPtrReturn(pProps, 0);
    1405 
    1406     uint32_t const uHz = pProps->uHz;
    1407     uint32_t cFrames;
    1408     if (cNs < RT_NS_1SEC)
    1409         cFrames = 0;
    1410     else
    1411     {
    1412         cFrames = cNs / RT_NS_1SEC * uHz;
    1413         cNs %= RT_NS_1SEC;
    1414     }
    1415     cFrames += (ASMMult2xU32RetU64(uHz, (uint32_t)cNs) + RT_NS_1SEC - 1) / RT_NS_1SEC;
    1416     return cFrames;
    1417 }
    1418 
    1419 /**
    1420  * Converts nanoseconds to bytes.
    1421  *
    1422  * @returns Number of bytes (frame aligned).
    1423  * @param   pProps      The PCM properties to use.
    1424  * @param   cNs         The number of nanoseconds to convert.
    1425  *
    1426  * @note    The result is rounded rather than floored (hysterical raisins).
    1427  */
    1428 uint32_t DrvAudioHlpNanoToBytes(PCPDMAUDIOPCMPROPS pProps, uint64_t cNs)
    1429 {
    1430     return PDMAUDIOPCMPROPS_F2B(pProps, DrvAudioHlpNanoToFrames(pProps, cNs));
    1431 }
     1439
     1440/*********************************************************************************************************************************
     1441*   Audio File Helpers                                                                                                           *
     1442*********************************************************************************************************************************/
    14321443
    14331444/**
Note: See TracChangeset for help on using the changeset viewer.

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