Changeset 89072 in vbox for trunk/src/VBox/ValidationKit/utils/audio
- Timestamp:
- May 17, 2021 7:20:36 AM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/audio/vkat.cpp
r89063 r89072 42 42 #include <iprt/uuid.h> 43 43 #include <iprt/test.h> 44 #include <iprt/formats/riff.h>45 44 46 45 #include <package-generated.h> … … 179 178 /** Pointer to a backend-only stream structure. */ 180 179 typedef AUDIOTESTDRVSTACKSTREAM *PAUDIOTESTDRVSTACKSTREAM; 181 182 /**183 * An open wave file.184 */185 typedef struct AUDIOTESTWAVEFILE186 {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;200 180 201 181 … … 1139 1119 if (RT_FAILURE(rc)) 1140 1120 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 union1168 {1169 uint8_t ab[512];1170 struct1171 {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_MAGIC1184 && uBuf.Wave.Hdr.uFileType == RTRIFF_FILE_TYPE_WAVE1185 && uBuf.Wave.Fmt.Chunk.uMagic == RTRIFFWAVEFMT_MAGIC1186 && 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 != 81195 && uBuf.Wave.Fmt.Data.cBitsPerSample != 161196 && 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 < 11199 || 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 < 40961202 || 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 else1211 {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 succeeding1223 * it, containing IART and other things we can ignored. Thus1224 * we read a list header here rather than just a chunk header,1225 * since it doesn't matter if we read 4 bytes extra as1226 * 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_MAGIC1233 && uBuf.List.uListType == RTRIFFLIST_TYPE_INFO1234 && 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_MAGIC1245 && uBuf.Data.Chunk.cbChunk <= pWaveFile->cbSamples1246 && 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 else1261 RTMsgError("%s: Failed to read data header: %Rrc", pszFile, rc);1262 }1263 }1264 else1265 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 else1271 RTMsgError("%s: Failed to read file header: %Rrc", pszFile, rc);1272 }1273 else1274 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 else1314 pWaveFile->offCur += cbBuf;1315 1121 } 1316 1122 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.