VirtualBox

Changeset 89465 in vbox


Ignore:
Timestamp:
Jun 2, 2021 1:03:23 PM (4 years ago)
Author:
vboxsync
Message:

AudioTest: Added support for writing wave files. bugref:10008

Location:
trunk/src/VBox/Devices/Audio
Files:
2 edited

Legend:

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

    r89463 r89465  
    14641464int AudioTestWaveFileOpen(const char *pszFile, PAUDIOTESTWAVEFILE pWaveFile, PRTERRINFO pErrInfo)
    14651465{
     1466    pWaveFile->u32Magic = AUDIOTESTWAVEFILE_MAGIC_DEAD;
    14661467    RT_ZERO(pWaveFile->Props);
    14671468    pWaveFile->hFile = NIL_RTFILE;
     
    16061607                             * We're good!
    16071608                             */
    1608                             pWaveFile->offCur = 0;
     1609                            pWaveFile->offCur    = 0;
     1610                            pWaveFile->fReadMode = true;
     1611                            pWaveFile->u32Magic  = AUDIOTESTWAVEFILE_MAGIC;
    16091612                            return VINF_SUCCESS;
    16101613                        }
     
    16351638}
    16361639
     1640
     1641/**
     1642 * Creates a new wave file.
     1643 *
     1644 * @returns VBox status code.
     1645 * @param   pszFile     The filename.
     1646 * @param   pProps      The audio format properties.
     1647 * @param   pWaveFile   The wave file structure to fill in on success.
     1648 * @param   pErrInfo    Where to return addition error details on failure.
     1649 */
     1650int AudioTestWaveFileCreate(const char *pszFile, PCPDMAUDIOPCMPROPS pProps, PAUDIOTESTWAVEFILE pWaveFile, PRTERRINFO pErrInfo)
     1651{
     1652    /*
     1653     * Construct the file header first (we'll do some input validation
     1654     * here, so better do it before creating the file).
     1655     */
     1656    struct
     1657    {
     1658        RTRIFFHDR               Hdr;
     1659        RTRIFFWAVEFMTEXTCHUNK   FmtExt;
     1660        RTRIFFCHUNK             Data;
     1661    } FileHdr;
     1662
     1663    FileHdr.Hdr.uMagic                      = RTRIFFHDR_MAGIC;
     1664    FileHdr.Hdr.cbFile                      = 0; /* need to update this later */
     1665    FileHdr.Hdr.uFileType                   = RTRIFF_FILE_TYPE_WAVE;
     1666    FileHdr.FmtExt.Chunk.uMagic             = RTRIFFWAVEFMT_MAGIC;
     1667    FileHdr.FmtExt.Chunk.cbChunk            = sizeof(RTRIFFWAVEFMTEXTCHUNK) - sizeof(RTRIFFCHUNK);
     1668    FileHdr.FmtExt.Data.Core.uFormatTag     = RTRIFFWAVEFMT_TAG_EXTENSIBLE;
     1669    FileHdr.FmtExt.Data.Core.cChannels      = PDMAudioPropsChannels(pProps);
     1670    FileHdr.FmtExt.Data.Core.uHz            = PDMAudioPropsHz(pProps);
     1671    FileHdr.FmtExt.Data.Core.cbRate         = PDMAudioPropsFramesToBytes(pProps, PDMAudioPropsHz(pProps));
     1672    FileHdr.FmtExt.Data.Core.cbFrame        = PDMAudioPropsFrameSize(pProps);
     1673    FileHdr.FmtExt.Data.Core.cBitsPerSample = PDMAudioPropsSampleBits(pProps);
     1674    FileHdr.FmtExt.Data.cbExtra             = sizeof(FileHdr.FmtExt.Data) - sizeof(FileHdr.FmtExt.Data.Core);
     1675    FileHdr.FmtExt.Data.cValidBitsPerSample = PDMAudioPropsSampleBits(pProps);
     1676    FileHdr.FmtExt.Data.fChannelMask        = 0;
     1677    for (uintptr_t idxCh = 0; idxCh < FileHdr.FmtExt.Data.Core.cChannels; idxCh++)
     1678    {
     1679        PDMAUDIOCHANNELID const idCh = (PDMAUDIOCHANNELID)pProps->aidChannels[idxCh];
     1680        if (   idCh >= PDMAUDIOCHANNELID_FIRST_STANDARD
     1681            && idCh <  PDMAUDIOCHANNELID_END_STANDARD)
     1682        {
     1683            if (!(FileHdr.FmtExt.Data.fChannelMask & RT_BIT_32(idCh - PDMAUDIOCHANNELID_FIRST_STANDARD)))
     1684                FileHdr.FmtExt.Data.fChannelMask |= RT_BIT_32(idCh - PDMAUDIOCHANNELID_FIRST_STANDARD);
     1685            else
     1686                return RTErrInfoSetF(pErrInfo, VERR_INVALID_PARAMETER, "Channel #%u repeats channel ID %d", idxCh, idCh);
     1687        }
     1688        else
     1689            return RTErrInfoSetF(pErrInfo, VERR_INVALID_PARAMETER, "Invalid channel ID %d for channel #%u", idCh, idxCh);
     1690    }
     1691
     1692    RTUUID UuidTmp;
     1693    int rc = RTUuidFromStr(&UuidTmp, RTRIFFWAVEFMTEXT_SUBTYPE_PCM);
     1694    AssertRCReturn(rc, rc);
     1695    FileHdr.FmtExt.Data.SubFormat = UuidTmp; /* (64-bit field maybe unaligned) */
     1696
     1697    FileHdr.Data.uMagic  = RTRIFFWAVEDATACHUNK_MAGIC;
     1698    FileHdr.Data.cbChunk = 0; /* need to update this later */
     1699
     1700    /*
     1701     * Create the file and write the header.
     1702     */
     1703    pWaveFile->hFile = NIL_RTFILE;
     1704    rc = RTFileOpen(&pWaveFile->hFile, pszFile, RTFILE_O_CREATE | RTFILE_O_WRITE | RTFILE_O_DENY_WRITE);
     1705    if (RT_FAILURE(rc))
     1706        return RTErrInfoSet(pErrInfo, rc, "RTFileOpen failed");
     1707
     1708    rc = RTFileWrite(pWaveFile->hFile, &FileHdr, sizeof(FileHdr), NULL);
     1709    if (RT_SUCCESS(rc))
     1710    {
     1711        /*
     1712         * Initialize the wave file structure.
     1713         */
     1714        pWaveFile->fReadMode       = false;
     1715        pWaveFile->offCur          = 0;
     1716        pWaveFile->offSamples      = 0;
     1717        pWaveFile->cbSamples       = 0;
     1718        pWaveFile->Props           = *pProps;
     1719        pWaveFile->offSamples      = RTFileTell(pWaveFile->hFile);
     1720        if (pWaveFile->offSamples != UINT32_MAX)
     1721        {
     1722            pWaveFile->u32Magic = AUDIOTESTWAVEFILE_MAGIC;
     1723            return VINF_SUCCESS;
     1724        }
     1725        rc = RTErrInfoSet(pErrInfo, VERR_SEEK, "RTFileTell failed");
     1726    }
     1727    else
     1728        RTErrInfoSet(pErrInfo, rc, "RTFileWrite failed writing header");
     1729
     1730    RTFileClose(pWaveFile->hFile);
     1731    pWaveFile->hFile    = NIL_RTFILE;
     1732    pWaveFile->u32Magic = AUDIOTESTWAVEFILE_MAGIC_DEAD;
     1733
     1734    RTFileDelete(pszFile);
     1735    return rc;
     1736}
     1737
     1738
    16371739/**
    16381740 * Closes a wave file.
    16391741 */
    1640 void AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile)
    1641 {
    1642     RTFileClose(pWaveFile->hFile);
    1643     pWaveFile->hFile = NIL_RTFILE;
     1742int AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile)
     1743{
     1744    AssertReturn(pWaveFile->u32Magic == AUDIOTESTWAVEFILE_MAGIC, VERR_INVALID_MAGIC);
     1745    int rcRet = VINF_SUCCESS;
     1746    int rc;
     1747
     1748    /*
     1749     * Update the size fields if writing.
     1750     */
     1751    if (!pWaveFile->fReadMode)
     1752    {
     1753        uint64_t cbFile = RTFileTell(pWaveFile->hFile);
     1754        if (cbFile != UINT64_MAX)
     1755        {
     1756            uint32_t cbFile32 = cbFile - sizeof(RTRIFFCHUNK);
     1757            rc = RTFileWriteAt(pWaveFile->hFile, RT_OFFSETOF(RTRIFFHDR, cbFile), &cbFile32, sizeof(cbFile32), NULL);
     1758            AssertRCStmt(rc, rcRet = rc);
     1759
     1760            uint32_t cbSamples = cbFile - pWaveFile->offSamples;
     1761            rc = RTFileWriteAt(pWaveFile->hFile, pWaveFile->offSamples - sizeof(uint32_t), &cbSamples, sizeof(cbSamples), NULL);
     1762            AssertRCStmt(rc, rcRet = rc);
     1763        }
     1764        else
     1765            rcRet = VERR_SEEK;
     1766    }
     1767
     1768    /*
     1769     * Close it.
     1770     */
     1771    rc = RTFileClose(pWaveFile->hFile);
     1772    AssertRCStmt(rc, rcRet = rc);
     1773
     1774    pWaveFile->hFile    = NIL_RTFILE;
     1775    pWaveFile->u32Magic = AUDIOTESTWAVEFILE_MAGIC_DEAD;
     1776    return rcRet;
    16441777}
    16451778
     
    16561789int AudioTestWaveFileRead(PAUDIOTESTWAVEFILE pWaveFile, void *pvBuf, size_t cbBuf, size_t *pcbRead)
    16571790{
     1791    AssertReturn(pWaveFile->u32Magic == AUDIOTESTWAVEFILE_MAGIC, VERR_INVALID_MAGIC);
     1792    AssertReturn(pWaveFile->fReadMode, VERR_ACCESS_DENIED);
     1793
    16581794    bool fEofAdjusted;
    16591795    if (pWaveFile->offCur + cbBuf <= pWaveFile->cbSamples)
     
    16841820}
    16851821
     1822
     1823/**
     1824 * Writes samples to a wave file.
     1825 *
     1826 * @returns VBox status code.
     1827 * @param   pWaveFile   The file to write to.
     1828 * @param   pvBuf       The samples to write.
     1829 * @param   cbBuf       How many bytes of samples to write.
     1830 */
     1831int AudioTestWaveFileWrite(PAUDIOTESTWAVEFILE pWaveFile, const void *pvBuf, size_t cbBuf)
     1832{
     1833    AssertReturn(pWaveFile->u32Magic == AUDIOTESTWAVEFILE_MAGIC, VERR_INVALID_MAGIC);
     1834    AssertReturn(!pWaveFile->fReadMode, VERR_ACCESS_DENIED);
     1835
     1836    pWaveFile->cbSamples += (uint32_t)cbBuf;
     1837    return RTFileWrite(pWaveFile->hFile, pvBuf, cbBuf, NULL);
     1838}
     1839
  • trunk/src/VBox/Devices/Audio/AudioTest.h

    r89463 r89465  
    336336typedef AUDIOTESTERRORDESC *PAUDIOTESTERRORDESC;
    337337
     338double AudioTestToneInit(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps, double dbFreq);
     339double AudioTestToneInitRandom(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps);
     340int    AudioTestToneGenerate(PAUDIOTESTTONE pTone, void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
     341
     342int    AudioTestToneParamsInitRandom(PAUDIOTESTTONEPARMS pToneParams, PPDMAUDIOPCMPROPS pProps);
     343
     344int    AudioTestPathCreateTemp(char *pszPath, size_t cbPath, const char *pszUUID);
     345int    AudioTestPathCreate(char *pszPath, size_t cbPath, const char *pszUUID);
     346
     347int    AudioTestSetObjCreateAndRegister(PAUDIOTESTSET pSet, const char *pszName, PAUDIOTESTOBJ *ppObj);
     348int    AudioTestSetObjWrite(PAUDIOTESTOBJ pObj, const void *pvBuf, size_t cbBuf);
     349int    AudioTestSetObjAddMetadataStr(PAUDIOTESTOBJ pObj, const char *pszFormat, ...);
     350int    AudioTestSetObjClose(PAUDIOTESTOBJ pObj);
     351
     352int    AudioTestSetTestBegin(PAUDIOTESTSET pSet, const char *pszDesc, PAUDIOTESTPARMS pParms, PAUDIOTESTENTRY *ppEntry);
     353int    AudioTestSetTestFailed(PAUDIOTESTENTRY pEntry, int rc, const char *pszErr);
     354int    AudioTestSetTestDone(PAUDIOTESTENTRY pEntry);
     355
     356int    AudioTestSetCreate(PAUDIOTESTSET pSet, const char *pszPath, const char *pszTag);
     357int    AudioTestSetDestroy(PAUDIOTESTSET pSet);
     358int    AudioTestSetOpen(PAUDIOTESTSET pSet, const char *pszPath);
     359int    AudioTestSetClose(PAUDIOTESTSET pSet);
     360int    AudioTestSetWipe(PAUDIOTESTSET pSet);
     361const char *AudioTestSetGetTag(PAUDIOTESTSET pSet);
     362bool   AudioTestSetIsPacked(const char *pszPath);
     363int    AudioTestSetPack(PAUDIOTESTSET pSet, const char *pszOutDir, char *pszFileName, size_t cbFileName);
     364int    AudioTestSetUnpack(const char *pszFile, const char *pszOutDir);
     365int    AudioTestSetVerify(PAUDIOTESTSET pSetA, PAUDIOTESTSET pSetB, PAUDIOTESTERRORDESC pErrDesc);
     366
     367bool   AudioTestErrorDescFailed(PAUDIOTESTERRORDESC pErr);
     368void   AudioTestErrorDescDestroy(PAUDIOTESTERRORDESC pErr);
     369
     370/** @name Wave File Accessors
     371 * @{ */
    338372/**
    339373 * An open wave (.WAV) file.
     
    341375typedef struct AUDIOTESTWAVEFILE
    342376{
     377    /** Magic value (AUDIOTESTWAVEFILE_MAGIC). */
     378    uint32_t            u32Magic;
     379    /** Set if we're in read-mode, clear if in write mode. */
     380    bool                fReadMode;
    343381    /** The file handle. */
    344382    RTFILE              hFile;
     
    355393typedef AUDIOTESTWAVEFILE *PAUDIOTESTWAVEFILE;
    356394
    357 
    358 double AudioTestToneInit(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps, double dbFreq);
    359 double AudioTestToneInitRandom(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps);
    360 int    AudioTestToneGenerate(PAUDIOTESTTONE pTone, void *pvBuf, uint32_t cbBuf, uint32_t *pcbWritten);
    361 
    362 int    AudioTestToneParamsInitRandom(PAUDIOTESTTONEPARMS pToneParams, PPDMAUDIOPCMPROPS pProps);
    363 
    364 int    AudioTestPathCreateTemp(char *pszPath, size_t cbPath, const char *pszUUID);
    365 int    AudioTestPathCreate(char *pszPath, size_t cbPath, const char *pszUUID);
    366 
    367 int    AudioTestSetObjCreateAndRegister(PAUDIOTESTSET pSet, const char *pszName, PAUDIOTESTOBJ *ppObj);
    368 int    AudioTestSetObjWrite(PAUDIOTESTOBJ pObj, const void *pvBuf, size_t cbBuf);
    369 int    AudioTestSetObjAddMetadataStr(PAUDIOTESTOBJ pObj, const char *pszFormat, ...);
    370 int    AudioTestSetObjClose(PAUDIOTESTOBJ pObj);
    371 
    372 int    AudioTestSetTestBegin(PAUDIOTESTSET pSet, const char *pszDesc, PAUDIOTESTPARMS pParms, PAUDIOTESTENTRY *ppEntry);
    373 int    AudioTestSetTestFailed(PAUDIOTESTENTRY pEntry, int rc, const char *pszErr);
    374 int    AudioTestSetTestDone(PAUDIOTESTENTRY pEntry);
    375 
    376 int    AudioTestSetCreate(PAUDIOTESTSET pSet, const char *pszPath, const char *pszTag);
    377 int    AudioTestSetDestroy(PAUDIOTESTSET pSet);
    378 int    AudioTestSetOpen(PAUDIOTESTSET pSet, const char *pszPath);
    379 int    AudioTestSetClose(PAUDIOTESTSET pSet);
    380 int    AudioTestSetWipe(PAUDIOTESTSET pSet);
    381 const char *AudioTestSetGetTag(PAUDIOTESTSET pSet);
    382 bool   AudioTestSetIsPacked(const char *pszPath);
    383 int    AudioTestSetPack(PAUDIOTESTSET pSet, const char *pszOutDir, char *pszFileName, size_t cbFileName);
    384 int    AudioTestSetUnpack(const char *pszFile, const char *pszOutDir);
    385 int    AudioTestSetVerify(PAUDIOTESTSET pSetA, PAUDIOTESTSET pSetB, PAUDIOTESTERRORDESC pErrDesc);
    386 
    387 bool   AudioTestErrorDescFailed(PAUDIOTESTERRORDESC pErr);
    388 void   AudioTestErrorDescDestroy(PAUDIOTESTERRORDESC pErr);
     395/** Magic value for AUDIOTESTWAVEFILE::u32Magic (Miles Dewey Davis III). */
     396#define AUDIOTESTWAVEFILE_MAGIC         UINT32_C(0x19260526)
     397/** Magic value for AUDIOTESTWAVEFILE::u32Magic after closing. */
     398#define AUDIOTESTWAVEFILE_MAGIC_DEAD    UINT32_C(0x19910928)
    389399
    390400int    AudioTestWaveFileOpen(const char *pszFile, PAUDIOTESTWAVEFILE pWaveFile, PRTERRINFO pErrInfo);
     401int    AudioTestWaveFileCreate(const char *pszFile, PCPDMAUDIOPCMPROPS pProps, PAUDIOTESTWAVEFILE pWaveFile, PRTERRINFO pErrInfo);
    391402int    AudioTestWaveFileRead(PAUDIOTESTWAVEFILE pWaveFile, void *pvBuf, size_t cbBuf, size_t *pcbRead);
    392 void   AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile);
     403int    AudioTestWaveFileWrite(PAUDIOTESTWAVEFILE pWaveFile, const void *pvBuf, size_t cbBuf);
     404int    AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile);
     405
     406/** @} */
    393407
    394408#endif /* !VBOX_INCLUDED_SRC_Audio_AudioTest_h */
Note: See TracChangeset for help on using the changeset viewer.

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