VirtualBox

Changeset 89072 in vbox for trunk/src/VBox/Devices/Audio


Ignore:
Timestamp:
May 17, 2021 7:20:36 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
144412
Message:

Audio/ValKit: Moved the AudioTestWaveXXX functions to AudioTest.cpp so those can also be used for injecting input (recording) data later. bugref:10008

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

Legend:

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

    r89054 r89072  
    2828#include <iprt/dir.h>
    2929#include <iprt/file.h>
     30#include <iprt/formats/riff.h>
    3031#include <iprt/inifile.h>
    3132#include <iprt/list.h>
     33#include <iprt/message.h> /** @todo Get rid of this once we have own log hooks. */
    3234#include <iprt/rand.h>
    3335#include <iprt/system.h>
     
    907909}
    908910
     911
     912/*********************************************************************************************************************************
     913*   WAVE File Reader.                                                                                                            *
     914*********************************************************************************************************************************/
     915/**
     916 * Opens a wave (.WAV) file for reading.
     917 *
     918 * @returns VBox status code.
     919 * @param   pszFile     The file to open.
     920 * @param   pWaveFile   The open wave file structure to fill in on success.
     921 */
     922int AudioTestWaveFileOpen(const char *pszFile, PAUDIOTESTWAVEFILE pWaveFile)
     923{
     924    RT_ZERO(pWaveFile->Props);
     925    pWaveFile->hFile = NIL_RTFILE;
     926    int rc = RTFileOpen(&pWaveFile->hFile, pszFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
     927    if (RT_FAILURE(rc))
     928        return rc;
     929    uint64_t cbFile = 0;
     930    rc = RTFileQuerySize(pWaveFile->hFile, &cbFile);
     931    if (RT_SUCCESS(rc))
     932    {
     933        union
     934        {
     935            uint8_t                 ab[512];
     936            struct
     937            {
     938                RTRIFFHDR           Hdr;
     939                RTRIFFWAVEFMTCHUNK  Fmt;
     940            } Wave;
     941            RTRIFFLIST              List;
     942            RTRIFFWAVEDATACHUNK     Data;
     943        } uBuf;
     944
     945        rc = RTFileRead(pWaveFile->hFile, &uBuf.Wave, sizeof(uBuf.Wave), NULL);
     946        if (RT_SUCCESS(rc))
     947        {
     948            rc = VERR_VFS_UNKNOWN_FORMAT;
     949            if (   uBuf.Wave.Hdr.uMagic    == RTRIFFHDR_MAGIC
     950                && uBuf.Wave.Hdr.uFileType == RTRIFF_FILE_TYPE_WAVE
     951                && uBuf.Wave.Fmt.Chunk.uMagic == RTRIFFWAVEFMT_MAGIC
     952                && uBuf.Wave.Fmt.Chunk.cbChunk >= sizeof(uBuf.Wave.Fmt.Data))
     953            {
     954                if (uBuf.Wave.Hdr.cbFile != cbFile - sizeof(RTRIFFCHUNK))
     955                    RTMsgWarning("%s: File size mismatch: %#x, actual %#RX64 (ignored)",
     956                                 pszFile, uBuf.Wave.Hdr.cbFile, cbFile - sizeof(RTRIFFCHUNK));
     957                rc = VERR_VFS_BOGUS_FORMAT;
     958                if (uBuf.Wave.Fmt.Data.uFormatTag != RTRIFFWAVEFMT_TAG_PCM)
     959                    RTMsgError("%s: Unsupported uFormatTag value: %u (expected 1)", pszFile, uBuf.Wave.Fmt.Data.uFormatTag);
     960                else if (   uBuf.Wave.Fmt.Data.cBitsPerSample != 8
     961                         && uBuf.Wave.Fmt.Data.cBitsPerSample != 16
     962                         && uBuf.Wave.Fmt.Data.cBitsPerSample != 32)
     963                    RTMsgError("%s: Unsupported cBitsPerSample value: %u", pszFile, uBuf.Wave.Fmt.Data.cBitsPerSample);
     964                else if (   uBuf.Wave.Fmt.Data.cChannels < 1
     965                         || uBuf.Wave.Fmt.Data.cChannels >= 16)
     966                    RTMsgError("%s: Unsupported cChannels value: %u (expected 1..15)", pszFile, uBuf.Wave.Fmt.Data.cChannels);
     967                else if (   uBuf.Wave.Fmt.Data.uHz < 4096
     968                         || uBuf.Wave.Fmt.Data.uHz > 768000)
     969                    RTMsgError("%s: Unsupported uHz value: %u (expected 4096..768000)", pszFile, uBuf.Wave.Fmt.Data.uHz);
     970                else if (uBuf.Wave.Fmt.Data.cbFrame != uBuf.Wave.Fmt.Data.cChannels * uBuf.Wave.Fmt.Data.cBitsPerSample / 8)
     971                    RTMsgError("%s: Invalid cbFrame value: %u (expected %u)", pszFile, uBuf.Wave.Fmt.Data.cbFrame,
     972                               uBuf.Wave.Fmt.Data.cChannels * uBuf.Wave.Fmt.Data.cBitsPerSample / 8);
     973                else if (uBuf.Wave.Fmt.Data.cbRate != uBuf.Wave.Fmt.Data.cbFrame * uBuf.Wave.Fmt.Data.uHz)
     974                    RTMsgError("%s: Invalid cbRate value: %u (expected %u)", pszFile, uBuf.Wave.Fmt.Data.cbRate,
     975                               uBuf.Wave.Fmt.Data.cbFrame * uBuf.Wave.Fmt.Data.uHz);
     976                else
     977                {
     978                    /*
     979                     * Copy out the data we need from the file format structure.
     980                     */
     981                    PDMAudioPropsInit(&pWaveFile->Props, uBuf.Wave.Fmt.Data.cBitsPerSample / 8, true /*fSigned*/,
     982                                      uBuf.Wave.Fmt.Data.cChannels, uBuf.Wave.Fmt.Data.uHz);
     983                    pWaveFile->offSamples = sizeof(RTRIFFHDR) + sizeof(RTRIFFCHUNK) + uBuf.Wave.Fmt.Chunk.cbChunk;
     984
     985                    /*
     986                     * Find the 'data' chunk with the audio samples.
     987                     *
     988                     * There can be INFO lists both preceeding this and succeeding
     989                     * it, containing IART and other things we can ignored.  Thus
     990                     * we read a list header here rather than just a chunk header,
     991                     * since it doesn't matter if we read 4 bytes extra as
     992                     * AudioTestWaveFileRead uses RTFileReadAt anyway.
     993                     */
     994                    rc = RTFileReadAt(pWaveFile->hFile, pWaveFile->offSamples, &uBuf, sizeof(uBuf.List), NULL);
     995                    if (RT_SUCCESS(rc))
     996                    {
     997                        /* HACK ALERT: Skip one INFO list and hope we find a data chunk following it: */
     998                        if (   uBuf.List.uMagic    == RTRIFFLIST_MAGIC
     999                            && uBuf.List.uListType ==  RTRIFFLIST_TYPE_INFO
     1000                            && uBuf.List.cbChunk   <= (uint32_t)cbFile - pWaveFile->offSamples - sizeof(RTRIFFCHUNK))
     1001                        {
     1002                            pWaveFile->offSamples += sizeof(RTRIFFCHUNK) + uBuf.List.cbChunk;
     1003                            rc = RTFileReadAt(pWaveFile->hFile, pWaveFile->offSamples, &uBuf, sizeof(uBuf.List), NULL);
     1004                        }
     1005
     1006                        pWaveFile->offSamples += sizeof(uBuf.Data.Chunk);
     1007                        pWaveFile->cbSamples   = (uint32_t)cbFile - pWaveFile->offSamples;
     1008
     1009                        rc = VERR_VFS_BOGUS_FORMAT;
     1010                        if (   uBuf.Data.Chunk.uMagic == RTRIFFWAVEDATACHUNK_MAGIC
     1011                            && uBuf.Data.Chunk.cbChunk <= pWaveFile->cbSamples
     1012                            && PDMAudioPropsIsSizeAligned(&pWaveFile->Props, uBuf.Data.Chunk.cbChunk))
     1013                        {
     1014                            pWaveFile->cbSamples = uBuf.Data.Chunk.cbChunk;
     1015                            /*
     1016                             * We're good!
     1017                             */
     1018                            pWaveFile->offCur = 0;
     1019                            return VINF_SUCCESS;
     1020                        }
     1021
     1022                        RTMsgError("%s: Bad data header: uMagic=%#x (expected %#x), cbChunk=%#x (max %#RX64, align %u)",
     1023                                   pszFile, uBuf.Data.Chunk.uMagic, RTRIFFWAVEDATACHUNK_MAGIC,
     1024                                   uBuf.Data.Chunk.cbChunk, pWaveFile->cbSamples, PDMAudioPropsFrameSize(&pWaveFile->Props));
     1025                    }
     1026                    else
     1027                        RTMsgError("%s: Failed to read data header: %Rrc", pszFile, rc);
     1028                }
     1029            }
     1030            else
     1031                RTMsgError("%s: Bad file header: uMagic=%#x (vs. %#x), uFileType=%#x (vs %#x), uFmtMagic=%#x (vs %#x) cbFmtChunk=%#x (min %#x)",
     1032                           pszFile, uBuf.Wave.Hdr.uMagic, RTRIFFHDR_MAGIC, uBuf.Wave.Hdr.uFileType, RTRIFF_FILE_TYPE_WAVE,
     1033                           uBuf.Wave.Fmt.Chunk.uMagic, RTRIFFWAVEFMT_MAGIC,
     1034                           uBuf.Wave.Fmt.Chunk.cbChunk, sizeof(uBuf.Wave.Fmt.Data));
     1035        }
     1036        else
     1037            RTMsgError("%s: Failed to read file header: %Rrc", pszFile, rc);
     1038    }
     1039    else
     1040        RTMsgError("%s: Failed to query file size: %Rrc", pszFile, rc);
     1041
     1042    RTFileClose(pWaveFile->hFile);
     1043    pWaveFile->hFile = NIL_RTFILE;
     1044    return rc;
     1045}
     1046
     1047/**
     1048 * Closes a wave file.
     1049 */
     1050void AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile)
     1051{
     1052    RTFileClose(pWaveFile->hFile);
     1053    pWaveFile->hFile = NIL_RTFILE;
     1054}
     1055
     1056/**
     1057 * Reads samples from a wave file.
     1058 *
     1059 * @returns VBox status code.  See RTVfsFileRead for EOF status handling.
     1060 * @param   pWaveFile   The file to read from.
     1061 * @param   pvBuf       Where to put the samples.
     1062 * @param   cbBuf       How much to read at most.
     1063 * @param   pcbRead     Where to return the actual number of bytes read,
     1064 *                      optional.
     1065 */
     1066int AudioTestWaveFileRead(PAUDIOTESTWAVEFILE pWaveFile, void *pvBuf, size_t cbBuf, size_t *pcbRead)
     1067{
     1068    int rc = RTFileReadAt(pWaveFile->hFile, pWaveFile->offCur, pvBuf, cbBuf, pcbRead);
     1069    if (RT_SUCCESS(rc))
     1070    {
     1071        if (pcbRead)
     1072        {
     1073            pWaveFile->offCur += *pcbRead;
     1074            if (cbBuf > *pcbRead)
     1075                rc = VINF_EOF;
     1076            else if (!cbBuf && pWaveFile->offCur == pWaveFile->cbSamples)
     1077                rc = VINF_EOF;
     1078        }
     1079        else
     1080            pWaveFile->offCur += cbBuf;
     1081    }
     1082    return rc;
     1083}
     1084
  • trunk/src/VBox/Devices/Audio/AudioTest.h

    r89051 r89072  
    235235typedef AUDIOTESTERRORDESC *PAUDIOTESTERRORDESC;
    236236
     237/**
     238 * An open wave (.WAV) file.
     239 */
     240typedef struct AUDIOTESTWAVEFILE
     241{
     242    /** The file handle. */
     243    RTFILE              hFile;
     244    /** The absolute file offset of the first sample */
     245    uint32_t            offSamples;
     246    /** Number of bytes of samples. */
     247    uint32_t            cbSamples;
     248    /** The current read position relative to @a offSamples.  */
     249    uint32_t            offCur;
     250    /** The PCM properties for the file format.  */
     251    PDMAUDIOPCMPROPS    Props;
     252} AUDIOTESTWAVEFILE;
     253/** Pointer to an open wave file. */
     254typedef AUDIOTESTWAVEFILE *PAUDIOTESTWAVEFILE;
     255
    237256
    238257double AudioTestToneInitRandom(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps);
     
    260279void   AudioTestErrorDescDestroy(PAUDIOTESTERRORDESC pErr);
    261280
     281int    AudioTestWaveFileOpen(const char *pszFile, PAUDIOTESTWAVEFILE pWaveFile);
     282int    AudioTestWaveFileRead(PAUDIOTESTWAVEFILE pWaveFile, void *pvBuf, size_t cbBuf, size_t *pcbRead);
     283void   AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile);
     284
    262285#endif /* !VBOX_INCLUDED_SRC_Audio_AudioTest_h */
    263286
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