VirtualBox

Changeset 88269 in vbox for trunk/include/VBox


Ignore:
Timestamp:
Mar 24, 2021 11:45:54 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
143474
Message:

Audio: Made sure PDMAUDIOPCMPROPS is initialized using a helper function or the initializer macro, and that vital changes are made using setting helper functions. There are now two derived fields (frame size and shift count) that must be maintained, so this was the sanest way of doing it. Added a raw flag to PDMAUDIOPCMPROPS for VRDE/VRDP, since it wants the raw mixer content and we need a way of expressing this (PDMAUDIOSTREAMLAYOUT isn't the right place). The mixer buffers now uses PDMAUDIOPCMPROPS rather than the weird 32-bit format contraption for picking conversion functions. Simplify the drvAudioStreamPlay code by eliminating the PDMAUDIOSTREAMLAYOUT_RAW special case. bugref:9890

Location:
trunk/include/VBox/vmm
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r88259 r88269  
    570570    /** Unknown access type; do not use (hdaR3StreamMapReset uses it). */
    571571    PDMAUDIOSTREAMLAYOUT_UNKNOWN,
    572     /** Non-interleaved access, that is, consecutive
    573      *  access to the data. */
     572    /** Non-interleaved access, that is, consecutive access to the data.
     573     * @todo r=bird: For plain stereo this is actually interleaves left/right.  What
     574     *       I guess non-interleaved means, is that there are no additional
     575     *       information interleaved next to the interleaved stereo.
     576     *       https://stackoverflow.com/questions/17879933/whats-the-interleaved-audio */
    574577    PDMAUDIOSTREAMLAYOUT_NON_INTERLEAVED,
    575     /** Interleaved access, where the data can be
    576      *  mixed together with data of other audio streams. */
     578    /** Interleaved access, where the data can be mixed together with data of other audio streams. */
    577579    PDMAUDIOSTREAMLAYOUT_INTERLEAVED,
    578     /** Complex layout, which does not fit into the
    579      *  interleaved / non-interleaved layouts. */
     580    /** Complex layout, which does not fit into the interleaved / non-interleaved layouts. */
    580581    PDMAUDIOSTREAMLAYOUT_COMPLEX,
    581582    /** Raw (pass through) data, with no data layout processing done.
    582583     *
    583584     *  This means that this stream will operate on PDMAUDIOFRAME data
    584      *  directly. Don't use this if you don't have to. */
     585     *  directly. Don't use this if you don't have to.
     586     *
     587     * @deprecated Replaced by S64 (signed, 64-bit sample size).  */
    585588    PDMAUDIOSTREAMLAYOUT_RAW,
    586589    /** End of valid values. */
     
    689692typedef struct PDMAUDIOPCMPROPS
    690693{
    691 /** @todo squeeze cbSample and cChannels into one uint8_t; Add cbFrame. */
     694    /** The frame size. */
     695    uint8_t     cbFrame;
    692696    /** Sample width (in bytes). */
    693     uint8_t     cbSample;
     697    uint8_t     cbSampleX : 4;
    694698    /** Number of audio channels. */
    695     uint8_t     cChannels;
     699    uint8_t     cChannelsX : 4;
    696700    /** Shift count used with PDMAUDIOPCMPROPS_F2B and PDMAUDIOPCMPROPS_B2F.
    697701     * Depends on number of stream channels and the stream format being used, calc
    698702     * value using PDMAUDIOPCMPROPS_MAKE_SHIFT.
    699      * @sa   PDMAUDIOSTREAMCFG_B2F, PDMAUDIOSTREAMCFG_F2B
    700      * @todo r=bird: The original brief description: "Shift count used
    701      *       for faster calculation of various values, such as the alignment, bytes
    702      *       to frames and so on."  I cannot make heads or tails from that.
    703      * @todo Use some RTAsmXXX functions instead? */
    704     uint8_t     cShift;
     703     * @sa   PDMAUDIOSTREAMCFG_B2F, PDMAUDIOSTREAMCFG_F2B */
     704    uint8_t     cShiftX;
    705705    /** Signed or unsigned sample. */
    706706    bool        fSigned : 1;
    707707    /** Whether the endianness is swapped or not. */
    708708    bool        fSwapEndian : 1;
     709    /** Raw mixer frames, only applicable for signed 64-bit samples. */
     710    bool        fRaw : 1;
    709711    /** Sample frequency in Hertz (Hz). */
    710712    uint32_t    uHz;
     
    719721/** @name Macros for use with PDMAUDIOPCMPROPS
    720722 * @{ */
    721 /** Initializer for PDMAUDIOPCMPROPS.
    722  * @todo /PDMAUDIOPCMPROPS_INITIALIZOR/PDMAUDIOPCMPROPS_INITIALIZER/ */
    723 #define PDMAUDIOPCMPROPS_INITIALIZOR(a_cBytes, a_fSigned, a_cCannels, a_uHz, a_cShift, a_fSwapEndian) \
    724     { a_cBytes, a_cCannels, a_cShift, a_fSigned, a_fSwapEndian, a_uHz }
     723/** Initializer for PDMAUDIOPCMPROPS. */
     724#define PDMAUDIOPCMPROPS_INITIALIZER(a_cbSample, a_fSigned, a_cChannels, a_uHz, a_fSwapEndian) \
     725    { (a_cbSample) * (a_cChannels), a_cbSample, a_cChannels, PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(a_cbSample, a_cChannels), \
     726      a_fSigned, a_fSwapEndian, false /*fRaw*/, a_uHz }
    725727/** Calculates the cShift value of given sample bits and audio channels.
    726  * @note This only works when the frame size is a
    727  * Does only support mono/stereo channels for now, for non-stereo/mono we
     728 * @note Does only support mono/stereo channels for now, for non-stereo/mono we
    728729 *       returns a special value which the two conversion functions detect
    729730 *       and make them fall back on cbSample * cChannels. */
     
    733734/** Calculates the cShift value of a PDMAUDIOPCMPROPS structure. */
    734735#define PDMAUDIOPCMPROPS_MAKE_SHIFT(pProps) \
    735     PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS((pProps)->cbSample, (pProps)->cChannels)
     736    PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS((pProps)->cbSampleX, (pProps)->cChannelsX)
    736737/** Converts (audio) frames to bytes.
    737  *  Needs the cShift value set correctly, using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
     738 * @note Requires properly initialized properties, i.e. cbFrames correctly calculated
     739 *       and cShift set using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
    738740#define PDMAUDIOPCMPROPS_F2B(pProps, cFrames) \
    739     ( (pProps)->cShift != UINT8_MAX ? (cFrames) << (pProps)->cShift : (cFrames) * ((pProps)->cbSample * (pProps)->cChannels) )
     741    ( (pProps)->cShiftX != UINT8_MAX ? (cFrames) << (pProps)->cShiftX : (cFrames) * (pProps)->cbFrame )
    740742/** Converts bytes to (audio) frames.
    741  *  Needs the cShift value set correctly, using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
     743 * @note Requires properly initialized properties, i.e. cbFrames correctly calculated
     744 *       and cShift set using PDMAUDIOPCMPROPS_MAKE_SHIFT. */
    742745#define PDMAUDIOPCMPROPS_B2F(pProps, cb) \
    743     ( (pProps)->cShift != UINT8_MAX ?      (cb) >> (pProps)->cShift : (cb)      / ((pProps)->cbSample * (pProps)->cChannels) )
     746    ( (pProps)->cShiftX != UINT8_MAX ?      (cb) >> (pProps)->cShiftX :      (cb) / (pProps)->cbFrame )
    744747/** @}   */
    745748
     
    766769     *  PDMAUDIOSTREAMLAYOUT_RAW:
    767770     *      Can be one or many streams at once, depending on the stream's mixing buffer setup.
    768      *      The audio data will get handled as PDMAUDIOFRAME frames without any modification done. */
     771     *      The audio data will get handled as PDMAUDIOFRAME frames without any modification done.
     772     *
     773     * @todo r=bird: See PDMAUDIOSTREAMLAYOUT comments. */
    769774    PDMAUDIOSTREAMLAYOUT    enmLayout;
    770775    /** Device emulation-specific data needed for the audio connector. */
     
    806811
    807812/** Converts (audio) frames to bytes. */
    808 #define PDMAUDIOSTREAMCFG_F2B(pCfg, frames) ((frames) << (pCfg->Props).cShift)
     813#define PDMAUDIOSTREAMCFG_F2B(pCfg, frames)     PDMAUDIOPCMPROPS_F2B(&(pCfg)->Props, (frames))
    809814/** Converts bytes to (audio) frames. */
    810 #define PDMAUDIOSTREAMCFG_B2F(pCfg, cb)  (cb >> (pCfg->Props).cShift)
     815#define PDMAUDIOSTREAMCFG_B2F(pCfg, cb)         PDMAUDIOPCMPROPS_B2F(&(pCfg)->Props, (cb))
    811816
    812817/**
     
    10081013    /** Magic value (PDMAUDIOMIXBUF_MAGIC). */
    10091014    uint32_t                    uMagic;
    1010     /** For quickly converting frames <-> bytes and vice versa. */
    1011     uint8_t                     cShift;
    1012     uint8_t                     abPadding[3];
     1015    uint8_t                     abPadding[4];
    10131016    /* ???Undocumented??? */
    10141017    RTLISTNODE                  Node;
     
    10481051     *       all?  */
    10491052    PDMAUDIOMIXBUFFMT           uAudioFmt;
     1053    /** Audio input properties.
     1054     * @note There is only one set of audio properties here because we have one
     1055     *       mixer buffer for the guest side and a separate one for the host side.
     1056     * @todo r=bird: Why exactly do we need to use separate mixer buffers?
     1057     *       Couldn't we just have different conversion fuctions and save the
     1058     *       extra copying? */
     1059    PDMAUDIOPCMPROPS            Props;
    10501060    /** Standard conversion-to function for set uAudioFmt. */
    10511061    PFNPDMAUDIOMIXBUFCONVTO     pfnConvTo;
    10521062    /** Standard conversion-from function for set uAudioFmt. */
    10531063    PFNPDMAUDIOMIXBUFCONVFROM   pfnConvFrom;
     1064
    10541065    /** Ratio of the associated parent stream's frequency by this stream's
    10551066     * frequency (1<<32), represented as a signed 64 bit integer.
  • trunk/include/VBox/vmm/pdmaudioinline.h

    r88136 r88269  
    365365    if (pCfg)
    366366        LogFunc(("szName=%s enmDir=%RU32 uHz=%RU32 cBits=%RU8%s cChannels=%RU8\n", pCfg->szName, pCfg->enmDir,
    367                  pCfg->Props.uHz, pCfg->Props.cbSample * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannels));
     367                 pCfg->Props.uHz, pCfg->Props.cbSampleX * 8, pCfg->Props.fSigned ? "S" : "U", pCfg->Props.cChannelsX));
    368368}
    369369
     
    467467
    468468/**
     469 * Initialize PCM audio properties.
     470 */
     471DECLINLINE(void) PDMAudioPropsInit(PPDMAUDIOPCMPROPS pProps, uint8_t cbSample, bool fSigned, uint8_t cChannels, uint32_t uHz)
     472{
     473    pProps->cbFrame     = cbSample * cChannels;
     474    pProps->cbSampleX   = cbSample;
     475    pProps->cChannelsX  = cChannels;
     476    pProps->cShiftX     = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cbSample, cChannels);
     477    pProps->fSigned     = fSigned;
     478    pProps->fSwapEndian = false;
     479    pProps->fRaw        = false;
     480    pProps->uHz         = uHz;
     481
     482    Assert(pProps->cbFrame    == (uint32_t)cbSample * cChannels);
     483    Assert(pProps->cbSampleX  == cbSample);
     484    Assert(pProps->cChannelsX == cChannels);
     485}
     486
     487/**
     488 * Initialize PCM audio properties, extended version.
     489 */
     490DECLINLINE(void) PDMAudioPropsInitEx(PPDMAUDIOPCMPROPS pProps, uint8_t cbSample, bool fSigned, uint8_t cChannels, uint32_t uHz,
     491                                     bool fLittleEndian, bool fRaw)
     492{
     493    Assert(!fRaw || cbSample == sizeof(int64_t));
     494    pProps->cbFrame     = cbSample * cChannels;
     495    pProps->cbSampleX   = cbSample;
     496    pProps->cChannelsX  = cChannels;
     497    pProps->cShiftX     = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cbSample, cChannels);
     498    pProps->fSigned     = fSigned;
     499#ifdef RT_LITTLE_ENDIAN
     500    pProps->fSwapEndian = !fLittleEndian;
     501#else
     502    pProps->fSwapEndian = fLittleEndian;
     503#endif
     504    pProps->fRaw        = fRaw;
     505    pProps->uHz         = uHz;
     506
     507    Assert(pProps->cbFrame    == (uint32_t)cbSample * cChannels);
     508    Assert(pProps->cbSampleX  == cbSample);
     509    Assert(pProps->cChannelsX == cChannels);
     510}
     511
     512/**
     513 * Modifies the channel count.
     514 *
     515 * @param   pProps              The PCM properties to update.
     516 * @param   cChannels           The new channel count.
     517 */
     518DECLINLINE(void) PDMAudioPropsSetChannels(PPDMAUDIOPCMPROPS pProps, uint8_t cChannels)
     519{
     520    Assert(cChannels > 0); Assert(cChannels < 16);
     521    pProps->cChannelsX  = cChannels;
     522    pProps->cbFrame     = pProps->cbSampleX * cChannels;
     523    pProps->cShiftX     = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cbSampleX, cChannels);
     524}
     525
     526/**
     527 * Modifies the sample size.
     528 *
     529 * @param   pProps              The PCM properties to update.
     530 * @param   cbSample            The new sample size (in bytes).
     531 */
     532DECLINLINE(void) PDMAudioPropsSetSampleSize(PPDMAUDIOPCMPROPS pProps, uint8_t cbSample)
     533{
     534    Assert(cbSample == 1 || cbSample == 2 || cbSample == 4 || cbSample == 8);
     535    pProps->cbSampleX   = cbSample;
     536    pProps->cbFrame     = cbSample * pProps->cChannelsX;
     537    pProps->cShiftX     = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(cbSample, pProps->cChannelsX);
     538}
     539
     540/**
    469541 * Gets the bitrate.
    470542 *
     
    476548DECLINLINE(uint32_t) PDMAudioPropsGetBitrate(PCPDMAUDIOPCMPROPS pProps)
    477549{
    478     return pProps->cbSample * pProps->cChannels * pProps->uHz * 8;
     550    Assert(pProps->cbFrame == pProps->cbSampleX * pProps->cChannelsX);
     551    return pProps->cbFrame * pProps->uHz * 8;
     552}
     553
     554/**
     555 * Gets the number of channels.
     556 * @returns The channel count.
     557 * @param   pProps      The PCM properties.
     558 */
     559DECL_FORCE_INLINE(uint8_t) PDMAudioPropsChannels(PCPDMAUDIOPCMPROPS pProps)
     560{
     561    return pProps->cChannelsX;
     562}
     563
     564/**
     565 * Gets the sample size in bytes.
     566 * @returns Number of bytes per sample.
     567 * @param   pProps      The PCM properties.
     568 */
     569DECL_FORCE_INLINE(uint8_t) PDMAudioPropsSampleSize(PCPDMAUDIOPCMPROPS pProps)
     570{
     571    return pProps->cbSampleX;
     572}
     573
     574/**
     575 * Gets the sample size in bits.
     576 * @returns Number of bits per sample.
     577 * @param   pProps      The PCM properties.
     578 */
     579DECLINLINE(uint8_t) PDMAudioPropsSampleBits(PCPDMAUDIOPCMPROPS pProps)
     580{
     581    return pProps->cbSampleX * 8;
     582}
     583
     584/**
     585 * Gets the frame size in bytes.
     586 * @returns Number of bytes per frame.
     587 * @param   pProps      The PCM properties.
     588 */
     589DECL_FORCE_INLINE(uint8_t) PDMAudioPropsFrameSize(PCPDMAUDIOPCMPROPS pProps)
     590{
     591    return pProps->cbFrame;
     592}
     593
     594/**
     595 * Gets the frequency.
     596 * @returns Frequency.
     597 * @param   pProps      The PCM properties.
     598 */
     599DECL_FORCE_INLINE(uint32_t) PDMAudioPropsHz(PCPDMAUDIOPCMPROPS pProps)
     600{
     601    return pProps->uHz;
     602}
     603
     604/**
     605 * Checks if the format is signed or unsigned.
     606 * @returns true if signed, false if unsigned.
     607 * @param   pProps      The PCM properties.
     608 */
     609DECL_FORCE_INLINE(bool) PDMAudioPropsIsSigned(PCPDMAUDIOPCMPROPS pProps)
     610{
     611    return pProps->fSigned;
     612}
     613
     614/**
     615 * Checks if the format is little-endian or not.
     616 * @returns true if little-endian (or if 8-bit), false if big-endian.
     617 * @param   pProps      The PCM properties.
     618 */
     619DECL_FORCE_INLINE(bool) PDMAudioPropsIsLittleEndian(PCPDMAUDIOPCMPROPS pProps)
     620{
     621#ifdef RT_LITTLE_ENDIAN
     622    return !pProps->fSwapEndian || pProps->cbSampleX < 2;
     623#else
     624    return pProps->fSwapEndian  || pProps->cbSampleX < 2;
     625#endif
     626}
     627
     628/**
     629 * Checks if the format is big-endian or not.
     630 * @returns true if big-endian (or if 8-bit), false if little-endian.
     631 * @param   pProps      The PCM properties.
     632 */
     633DECL_FORCE_INLINE(bool) PDMAudioPropsIsBigEndian(PCPDMAUDIOPCMPROPS pProps)
     634{
     635#ifdef RT_LITTLE_ENDIAN
     636    return pProps->fSwapEndian || pProps->cbSampleX < 2;
     637#else
     638    return !pProps->fSwapEndian  || pProps->cbSampleX < 2;
     639#endif
    479640}
    480641
     
    775936     */
    776937    AssertPtrReturnVoid(pProps);
    777     Assert(pProps->cbSample);
     938    Assert(pProps->cbSampleX);
    778939    if (!cbBuf || !cFrames)
    779940        return;
     
    788949    AssertStmt(cbToClear <= cbBuf, cbToClear = cbBuf);
    789950
    790     Log2Func(("pProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cBytes=%RU8\n",
    791               pProps, pvBuf, cFrames, pProps->fSigned, pProps->cbSample));
     951    Log2Func(("pProps=%p, pvBuf=%p, cFrames=%RU32, fSigned=%RTbool, cbSample=%RU8\n",
     952              pProps, pvBuf, cFrames, pProps->fSigned, pProps->cbSampleX));
    792953
    793954    /*
     
    798959    else /* Unsigned formats. */
    799960    {
    800         switch (pProps->cbSample)
     961        switch (pProps->cbSampleX)
    801962        {
    802963            case 1: /* 8 bit */
     
    820981
    821982            default:
    822                 AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pProps->cbSample));
     983                AssertMsgFailed(("Invalid bytes per sample: %RU8\n", pProps->cbSampleX));
    823984        }
    824985    }
     
    8411002
    8421003    return pProps1->uHz         == pProps2->uHz
    843         && pProps1->cChannels   == pProps2->cChannels
    844         && pProps1->cbSample    == pProps2->cbSample
     1004        && pProps1->cChannelsX  == pProps2->cChannelsX
     1005        && pProps1->cbSampleX   == pProps2->cbSampleX
    8451006        && pProps1->fSigned     == pProps2->fSigned
    8461007        && pProps1->fSwapEndian == pProps2->fSwapEndian;
     
    8621023    AssertPtrReturn(pProps, false);
    8631024
    864     AssertReturn(pProps->cChannels != 0, false);
    865     AssertMsgReturn(pProps->cbSample == 1 || pProps->cbSample == 2 || pProps->cbSample == 4,
    866                     ("%u\n", pProps->cbSample), false);
     1025    AssertReturn(pProps->cChannelsX != 0, false);
     1026    AssertMsgReturn(   pProps->cbSampleX == 1 || pProps->cbSampleX == 2 || pProps->cbSampleX == 4  || (pProps->cbSampleX == 8 && pProps->fRaw),
     1027                    ("%u\n", pProps->cbSampleX), false);
     1028    AssertMsgReturn(pProps->cbFrame == pProps->cbSampleX * pProps->cChannelsX,
     1029                    ("cbFrame=%u cbSample=%u cChannels=%u\n", pProps->cbFrame, pProps->cbSampleX, pProps->cChannelsX),
     1030                    false);
    8671031    AssertMsgReturn(pProps->uHz >= 1000 && pProps->uHz < 1000000, ("%u\n", pProps->uHz), false);
    868     AssertMsgReturn(pProps->cShift == PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pProps->cbSample, pProps->cChannels),
    869                     ("cShift=%u cbSample=%u cChannels=%u\n", pProps->cShift, pProps->cbSample, pProps->cChannels),
     1032    AssertMsgReturn(pProps->cShiftX == PDMAUDIOPCMPROPS_MAKE_SHIFT(pProps),
     1033                    ("cShift=%u cbSample=%u cChannels=%u\n", pProps->cShiftX, pProps->cbSampleX, pProps->cChannelsX),
    8701034                    false);
     1035    AssertReturn(!pProps->fRaw || (pProps->fSigned && pProps->cbSampleX == sizeof(int64_t)), false);
    8711036    return true;
    8721037}
     
    8871052 * Prints PCM properties to the debug log.
    8881053 *
    889  * @param   pProps              Stream configuration to log.
     1054 * @param   pProps  PCM properties to use.
    8901055 */
    8911056DECLINLINE(void) PDMAudioPropsLog(PCPDMAUDIOPCMPROPS pProps)
     
    8941059
    8951060    Log(("uHz=%RU32, cChannels=%RU8, cBits=%RU8%s",
    896          pProps->uHz, pProps->cChannels, pProps->cbSample * 8, pProps->fSigned ? "S" : "U"));
    897 }
     1061         pProps->uHz, pProps->cChannelsX, pProps->cbSampleX * 8, pProps->fSigned ? "S" : "U"));
     1062}
     1063
     1064/** Max necessary buffer space for  PDMAudioPropsToString  */
     1065#define PDMAUDIOPROPSTOSTRING_MAX   sizeof("16ch S64 4294967296Hz swap raw")
     1066
     1067/**
     1068 * Formats the PCM audio properties into a string buffer.
     1069 *
     1070 * @returns pszDst
     1071 * @param   pProps  PCM properties to use.
     1072 * @param   pszDst  The destination buffer.
     1073 * @param   cchDst  The size of the destination buffer.  Recommended to be at
     1074 *                  least PDMAUDIOPROPSTOSTRING_MAX bytes.
     1075 */
     1076DECLINLINE(char *) PDMAudioPropsToString(PCPDMAUDIOPCMPROPS pProps, char *pszDst, size_t cchDst)
     1077{
     1078    /* 2ch S64 44100Hz swap raw */
     1079    RTStrPrintf(pszDst, cchDst, "%uch %c%u %RU32Hz%s%s",
     1080                PDMAudioPropsChannels(pProps), PDMAudioPropsIsSigned(pProps) ? 'S' : 'U', PDMAudioPropsSampleBits(pProps),
     1081                PDMAudioPropsHz(pProps), pProps->fSwapEndian ? " swap" : "", pProps->fRaw ? " raw" : "");
     1082    return pszDst;
     1083}
     1084
     1085
    8981086
    8991087/** @} */
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