VirtualBox

Ignore:
Timestamp:
May 17, 2021 7:20:36 AM (4 years ago)
Author:
vboxsync
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp

    r89063 r89072  
    4242#include <iprt/uuid.h>
    4343#include <iprt/test.h>
    44 #include <iprt/formats/riff.h>
    4544
    4645#include <package-generated.h>
     
    179178/** Pointer to a backend-only stream structure. */
    180179typedef AUDIOTESTDRVSTACKSTREAM *PAUDIOTESTDRVSTACKSTREAM;
    181 
    182 /**
    183  * An open wave file.
    184  */
    185 typedef struct AUDIOTESTWAVEFILE
    186 {
    187     /** The file handle. */
    188     RTFILE              hFile;
    189     /** The absolute file offset of the first sample */
    190     uint32_t            offSamples;
    191     /** Number of bytes of samples. */
    192     uint32_t            cbSamples;
    193     /** The current read position relative to @a offSamples.  */
    194     uint32_t            offCur;
    195     /** The PCM properties for the file format.  */
    196     PDMAUDIOPCMPROPS    Props;
    197 } AUDIOTESTWAVEFILE;
    198 /** Pointer to an open wave file. */
    199 typedef AUDIOTESTWAVEFILE *PAUDIOTESTWAVEFILE;
    200180
    201181
     
    11391119        if (RT_FAILURE(rc))
    11401120            RTTestFailed(g_hTest, "PDMIHOSTAUDIO::pfnStreamPlay(,,,%#x) failed: %Rrc", cbBuf, rc);
    1141     }
    1142     return rc;
    1143 }
    1144 
    1145 
    1146 /*********************************************************************************************************************************
    1147 *   WAVE File Reader.                                                                                                            *
    1148 *********************************************************************************************************************************/
    1149 /**
    1150  * Opens a wave-file for reading.
    1151  *
    1152  * @returns VBox status code.
    1153  * @param   pszFile     The file to open.
    1154  * @param   pWaveFile   The open wave file structure to fill in on success.
    1155  */
    1156 static int AudioTestWaveFileOpen(const char *pszFile, PAUDIOTESTWAVEFILE pWaveFile)
    1157 {
    1158     RT_ZERO(pWaveFile->Props);
    1159     pWaveFile->hFile = NIL_RTFILE;
    1160     int rc = RTFileOpen(&pWaveFile->hFile, pszFile, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
    1161     if (RT_FAILURE(rc))
    1162         return rc;
    1163     uint64_t cbFile = 0;
    1164     rc = RTFileQuerySize(pWaveFile->hFile, &cbFile);
    1165     if (RT_SUCCESS(rc))
    1166     {
    1167         union
    1168         {
    1169             uint8_t                 ab[512];
    1170             struct
    1171             {
    1172                 RTRIFFHDR           Hdr;
    1173                 RTRIFFWAVEFMTCHUNK  Fmt;
    1174             } Wave;
    1175             RTRIFFLIST              List;
    1176             RTRIFFWAVEDATACHUNK     Data;
    1177         } uBuf;
    1178 
    1179         rc = RTFileRead(pWaveFile->hFile, &uBuf.Wave, sizeof(uBuf.Wave), NULL);
    1180         if (RT_SUCCESS(rc))
    1181         {
    1182             rc = VERR_VFS_UNKNOWN_FORMAT;
    1183             if (   uBuf.Wave.Hdr.uMagic    == RTRIFFHDR_MAGIC
    1184                 && uBuf.Wave.Hdr.uFileType == RTRIFF_FILE_TYPE_WAVE
    1185                 && uBuf.Wave.Fmt.Chunk.uMagic == RTRIFFWAVEFMT_MAGIC
    1186                 && uBuf.Wave.Fmt.Chunk.cbChunk >= sizeof(uBuf.Wave.Fmt.Data))
    1187             {
    1188                 if (uBuf.Wave.Hdr.cbFile != cbFile - sizeof(RTRIFFCHUNK))
    1189                     RTMsgWarning("%s: File size mismatch: %#x, actual %#RX64 (ignored)",
    1190                                  pszFile, uBuf.Wave.Hdr.cbFile, cbFile - sizeof(RTRIFFCHUNK));
    1191                 rc = VERR_VFS_BOGUS_FORMAT;
    1192                 if (uBuf.Wave.Fmt.Data.uFormatTag != RTRIFFWAVEFMT_TAG_PCM)
    1193                     RTMsgError("%s: Unsupported uFormatTag value: %u (expected 1)", pszFile, uBuf.Wave.Fmt.Data.uFormatTag);
    1194                 else if (   uBuf.Wave.Fmt.Data.cBitsPerSample != 8
    1195                          && uBuf.Wave.Fmt.Data.cBitsPerSample != 16
    1196                          && uBuf.Wave.Fmt.Data.cBitsPerSample != 32)
    1197                     RTMsgError("%s: Unsupported cBitsPerSample value: %u", pszFile, uBuf.Wave.Fmt.Data.cBitsPerSample);
    1198                 else if (   uBuf.Wave.Fmt.Data.cChannels < 1
    1199                          || uBuf.Wave.Fmt.Data.cChannels >= 16)
    1200                     RTMsgError("%s: Unsupported cChannels value: %u (expected 1..15)", pszFile, uBuf.Wave.Fmt.Data.cChannels);
    1201                 else if (   uBuf.Wave.Fmt.Data.uHz < 4096
    1202                          || uBuf.Wave.Fmt.Data.uHz > 768000)
    1203                     RTMsgError("%s: Unsupported uHz value: %u (expected 4096..768000)", pszFile, uBuf.Wave.Fmt.Data.uHz);
    1204                 else if (uBuf.Wave.Fmt.Data.cbFrame != uBuf.Wave.Fmt.Data.cChannels * uBuf.Wave.Fmt.Data.cBitsPerSample / 8)
    1205                     RTMsgError("%s: Invalid cbFrame value: %u (expected %u)", pszFile, uBuf.Wave.Fmt.Data.cbFrame,
    1206                                uBuf.Wave.Fmt.Data.cChannels * uBuf.Wave.Fmt.Data.cBitsPerSample / 8);
    1207                 else if (uBuf.Wave.Fmt.Data.cbRate != uBuf.Wave.Fmt.Data.cbFrame * uBuf.Wave.Fmt.Data.uHz)
    1208                     RTMsgError("%s: Invalid cbRate value: %u (expected %u)", pszFile, uBuf.Wave.Fmt.Data.cbRate,
    1209                                uBuf.Wave.Fmt.Data.cbFrame * uBuf.Wave.Fmt.Data.uHz);
    1210                 else
    1211                 {
    1212                     /*
    1213                      * Copy out the data we need from the file format structure.
    1214                      */
    1215                     PDMAudioPropsInit(&pWaveFile->Props, uBuf.Wave.Fmt.Data.cBitsPerSample / 8, true /*fSigned*/,
    1216                                       uBuf.Wave.Fmt.Data.cChannels, uBuf.Wave.Fmt.Data.uHz);
    1217                     pWaveFile->offSamples = sizeof(RTRIFFHDR) + sizeof(RTRIFFCHUNK) + uBuf.Wave.Fmt.Chunk.cbChunk;
    1218 
    1219                     /*
    1220                      * Find the 'data' chunk with the audio samples.
    1221                      *
    1222                      * There can be INFO lists both preceeding this and succeeding
    1223                      * it, containing IART and other things we can ignored.  Thus
    1224                      * we read a list header here rather than just a chunk header,
    1225                      * since it doesn't matter if we read 4 bytes extra as
    1226                      * AudioTestWaveFileRead uses RTFileReadAt anyway.
    1227                      */
    1228                     rc = RTFileReadAt(pWaveFile->hFile, pWaveFile->offSamples, &uBuf, sizeof(uBuf.List), NULL);
    1229                     if (RT_SUCCESS(rc))
    1230                     {
    1231                         /* HACK ALERT: Skip one INFO list and hope we find a data chunk following it: */
    1232                         if (   uBuf.List.uMagic    == RTRIFFLIST_MAGIC
    1233                             && uBuf.List.uListType ==  RTRIFFLIST_TYPE_INFO
    1234                             && uBuf.List.cbChunk   <= (uint32_t)cbFile - pWaveFile->offSamples - sizeof(RTRIFFCHUNK))
    1235                         {
    1236                             pWaveFile->offSamples += sizeof(RTRIFFCHUNK) + uBuf.List.cbChunk;
    1237                             rc = RTFileReadAt(pWaveFile->hFile, pWaveFile->offSamples, &uBuf, sizeof(uBuf.List), NULL);
    1238                         }
    1239 
    1240                         pWaveFile->offSamples += sizeof(uBuf.Data.Chunk);
    1241                         pWaveFile->cbSamples   = (uint32_t)cbFile - pWaveFile->offSamples;
    1242 
    1243                         rc = VERR_VFS_BOGUS_FORMAT;
    1244                         if (   uBuf.Data.Chunk.uMagic == RTRIFFWAVEDATACHUNK_MAGIC
    1245                             && uBuf.Data.Chunk.cbChunk <= pWaveFile->cbSamples
    1246                             && PDMAudioPropsIsSizeAligned(&pWaveFile->Props, uBuf.Data.Chunk.cbChunk))
    1247                         {
    1248                             pWaveFile->cbSamples = uBuf.Data.Chunk.cbChunk;
    1249                             /*
    1250                              * We're good!
    1251                              */
    1252                             pWaveFile->offCur = 0;
    1253                             return VINF_SUCCESS;
    1254                         }
    1255 
    1256                         RTMsgError("%s: Bad data header: uMagic=%#x (expected %#x), cbChunk=%#x (max %#RX64, align %u)",
    1257                                    pszFile, uBuf.Data.Chunk.uMagic, RTRIFFWAVEDATACHUNK_MAGIC,
    1258                                    uBuf.Data.Chunk.cbChunk, pWaveFile->cbSamples, PDMAudioPropsFrameSize(&pWaveFile->Props));
    1259                     }
    1260                     else
    1261                         RTMsgError("%s: Failed to read data header: %Rrc", pszFile, rc);
    1262                 }
    1263             }
    1264             else
    1265                 RTMsgError("%s: Bad file header: uMagic=%#x (vs. %#x), uFileType=%#x (vs %#x), uFmtMagic=%#x (vs %#x) cbFmtChunk=%#x (min %#x)",
    1266                            pszFile, uBuf.Wave.Hdr.uMagic, RTRIFFHDR_MAGIC, uBuf.Wave.Hdr.uFileType, RTRIFF_FILE_TYPE_WAVE,
    1267                            uBuf.Wave.Fmt.Chunk.uMagic, RTRIFFWAVEFMT_MAGIC,
    1268                            uBuf.Wave.Fmt.Chunk.cbChunk, sizeof(uBuf.Wave.Fmt.Data));
    1269         }
    1270         else
    1271             RTMsgError("%s: Failed to read file header: %Rrc", pszFile, rc);
    1272     }
    1273     else
    1274         RTMsgError("%s: Failed to query file size: %Rrc", pszFile, rc);
    1275 
    1276     RTFileClose(pWaveFile->hFile);
    1277     pWaveFile->hFile = NIL_RTFILE;
    1278     return rc;
    1279 }
    1280 
    1281 /**
    1282  * Closes a wave file.
    1283  */
    1284 static void AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile)
    1285 {
    1286     RTFileClose(pWaveFile->hFile);
    1287     pWaveFile->hFile = NIL_RTFILE;
    1288 }
    1289 
    1290 /**
    1291  * Reads samples from a wave file.
    1292  *
    1293  * @returns VBox status code.  See RTVfsFileRead for EOF status handling.
    1294  * @param   pWaveFile   The file to read from.
    1295  * @param   pvBuf       Where to put the samples.
    1296  * @param   cbBuf       How much to read at most.
    1297  * @param   pcbRead     Where to return the actual number of bytes read,
    1298  *                      optional.
    1299  */
    1300 static int AudioTestWaveFileRead(PAUDIOTESTWAVEFILE pWaveFile, void *pvBuf, size_t cbBuf, size_t *pcbRead)
    1301 {
    1302     int rc = RTFileReadAt(pWaveFile->hFile, pWaveFile->offCur, pvBuf, cbBuf, pcbRead);
    1303     if (RT_SUCCESS(rc))
    1304     {
    1305         if (pcbRead)
    1306         {
    1307             pWaveFile->offCur += *pcbRead;
    1308             if (cbBuf > *pcbRead)
    1309                 rc = VINF_EOF;
    1310             else if (!cbBuf && pWaveFile->offCur == pWaveFile->cbSamples)
    1311                 rc = VINF_EOF;
    1312         }
    1313         else
    1314             pWaveFile->offCur += cbBuf;
    13151121    }
    13161122    return rc;
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