Changeset 89072 in vbox for trunk/src/VBox
- Timestamp:
- May 17, 2021 7:20:36 AM (4 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/AudioTest.cpp
r89054 r89072 28 28 #include <iprt/dir.h> 29 29 #include <iprt/file.h> 30 #include <iprt/formats/riff.h> 30 31 #include <iprt/inifile.h> 31 32 #include <iprt/list.h> 33 #include <iprt/message.h> /** @todo Get rid of this once we have own log hooks. */ 32 34 #include <iprt/rand.h> 33 35 #include <iprt/system.h> … … 907 909 } 908 910 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 */ 922 int 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 */ 1050 void 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 */ 1066 int 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 235 235 typedef AUDIOTESTERRORDESC *PAUDIOTESTERRORDESC; 236 236 237 /** 238 * An open wave (.WAV) file. 239 */ 240 typedef 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. */ 254 typedef AUDIOTESTWAVEFILE *PAUDIOTESTWAVEFILE; 255 237 256 238 257 double AudioTestToneInitRandom(PAUDIOTESTTONE pTone, PPDMAUDIOPCMPROPS pProps); … … 260 279 void AudioTestErrorDescDestroy(PAUDIOTESTERRORDESC pErr); 261 280 281 int AudioTestWaveFileOpen(const char *pszFile, PAUDIOTESTWAVEFILE pWaveFile); 282 int AudioTestWaveFileRead(PAUDIOTESTWAVEFILE pWaveFile, void *pvBuf, size_t cbBuf, size_t *pcbRead); 283 void AudioTestWaveFileClose(PAUDIOTESTWAVEFILE pWaveFile); 284 262 285 #endif /* !VBOX_INCLUDED_SRC_Audio_AudioTest_h */ 263 286 -
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.