GetStreamLatency Shared mode: 1x period + a little, but some 192000 devices return 5.3334ms. Exclusive mode: testbot returns 2x period + a little, but some HDA drivers return 1x period, some + a little.
GetBufferSize BufferSize must be rounded up, maximum 2s says MSDN. Both is wrong. Rounding may lead to size a little smaller than duration; duration > 2s is accepted in shared mode. Shared mode: round solely w.r.t. mixer rate, duration is no multiple of period. Exclusive mode: size appears as a multiple of some fragment that is either the rounded period or a fixed constant like 1024, whatever the driver implements.
IAudioClient_Stop Exclusive mode: the audio engine appears to drop frames, bumping GetPosition to a higher value than time allows, even allowing GetPosition > sum Released - GetCurrentPadding (testbot) Shared mode: no drop observed (or too small to be visible). GetPosition = sum Released - GetCurrentPadding Bugs: Some USB headset system drained the whole buffer, leaving padding 0 and bumping pos to sum minus 17 frames!
861{
874
876
877 hr = IMMDevice_Activate(
dev, &IID_IAudioClient, CLSCTX_INPROC_SERVER,
879 ok(
hr ==
S_OK,
"Activation failed with %08x\n",
hr);
881 return;
882
883 hr = IAudioClient_GetMixFormat(ac, &pwfx);
884 ok(
hr ==
S_OK,
"GetMixFormat failed: %08x\n",
hr);
886 return;
887
888 hr = IAudioClient_GetDevicePeriod(ac, &defp, &minp);
889 ok(
hr ==
S_OK,
"GetDevicePeriod failed: %08x\n",
hr);
890 ok(minp <= period,
"desired period %u too small for %u\n", (
ULONG)period, (
ULONG)minp);
891
892 if (share) {
893 trace(
"Testing shared mode\n");
894
896 0, duration, period, pwfx,
NULL);
897 period = defp;
898 } else {
906
908 0, duration, period, pwfx,
NULL);
909 }
910 ok(share ?
hr ==
S_OK :
hr ==
hexcl ||
hr == AUDCLNT_E_DEVICE_IN_USE,
"Initialize failed: %08x\n",
hr);
913 IAudioClient_Release(ac);
914 if(
hr == AUDCLNT_E_DEVICE_IN_USE)
915 skip(
"Device in use, no %s access\n", share ?
"shared" :
"exclusive");
916 return;
917 }
918
923 hr = IAudioClient_GetStreamLatency(ac, &t2);
924 ok(
hr ==
S_OK,
"GetStreamLatency failed: %08x\n",
hr);
925 trace(
"Latency: %u.%04u ms\n", (
UINT)(t2/10000), (
UINT)(t2 % 10000));
928 "Latency < default period, delta %ldus\n", (long)((t2-period)/10));
929
939 hr = IAudioClient_GetBufferSize(ac, &gbsize);
940 ok(
hr ==
S_OK,
"GetBufferSize failed: %08x\n",
hr);
941
945 trace(
"BufferSize %u estimated fragment %u x %u = %u\n", gbsize, fragment,
parts, fragment *
parts);
946
947
948
949 if (share)
952 else
954 "BufferSize %u misfits fragment size %u at rate %u\n", gbsize, fragment, pwfx->
nSamplesPerSec);
955
956
957
958
959
960
961
962
963
964 hr = IAudioClient_GetService(ac, &IID_IAudioClock, (
void**)&acl);
965 ok(
hr ==
S_OK,
"GetService(IAudioClock) failed: %08x\n",
hr);
966
967 hr = IAudioClock_GetFrequency(acl, &freq);
968 ok(
hr ==
S_OK,
"GetFrequency failed: %08x\n",
hr);
969 trace(
"Clock Frequency %u\n", (
UINT)freq);
970
971
972 if (share)
974 "Clock Frequency %u\n", (
UINT)freq);
975 else
977 "Clock Frequency %u\n", (
UINT)freq);
978
979 hr = IAudioClock_GetPosition(acl,
NULL,
NULL);
981
982 pcpos0 = 0;
983 hr = IAudioClock_GetPosition(acl, &
pos, &pcpos0);
984 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
985 ok(
pos == 0,
"GetPosition returned non-zero pos before being started\n");
986 ok(pcpos0 != 0,
"GetPosition returned zero pcpos\n");
987
988 hr = IAudioClient_GetService(ac, &IID_IAudioRenderClient, (
void**)&arc);
989 ok(
hr ==
S_OK,
"GetService(IAudioRenderClient) failed: %08x\n",
hr);
990
991 hr = IAudioRenderClient_GetBuffer(arc, gbsize+1, &
data);
992 ok(
hr == AUDCLNT_E_BUFFER_TOO_LARGE,
"GetBuffer too large failed: %08x\n",
hr);
993
996 hr = IAudioRenderClient_GetBuffer(arc,
avail, &
data);
997 ok(
hr ==
S_OK,
"GetBuffer failed: %08x\n",
hr);
999
1002 ok(
hr ==
S_OK,
"ReleaseBuffer failed: %08x\n",
hr);
1004
1005 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1006 ok(
hr ==
S_OK,
"GetCurrentPadding failed: %08x\n",
hr);
1007 ok(pad ==
sum,
"padding %u prior to start\n", pad);
1008
1009 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1010 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1011 ok(
pos == 0,
"GetPosition returned non-zero pos before being started\n");
1012
1013 hr = IAudioClient_Start(ac);
1015
1017 slept += 100;
1018
1019 hr = IAudioClient_GetStreamLatency(ac, &t1);
1020 ok(
hr ==
S_OK,
"GetStreamLatency failed: %08x\n",
hr);
1021 ok(t1 == t2,
"Latency not constant, delta %ld\n", (
long)(t1-t2));
1022
1023 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1024 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1026
1027 ok(
pos*1000/freq <= slept*1.4,
"Position %u too far after playing %ums\n", (
UINT)
pos, slept);
1029
1030 hr = IAudioClient_Stop(ac);
1032
1033 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1034 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1038 ok(
pos*1000/freq <= slept*1.1,
"Position %u too far after stop %ums\n", (
UINT)
pos, slept);
1039
1040 hr = IAudioClient_Start(ac);
1042
1044 slept += 100;
1045
1046 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1047 ok(
hr ==
S_OK,
"GetCurrentPadding failed: %08x\n",
hr);
1048 trace(
"padding %u past sleep #2\n", pad);
1049
1059 hr = IAudioClient_Stop(ac);
1061
1062 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1063 ok(
hr ==
S_OK,
"GetCurrentPadding failed: %08x\n",
hr);
1064
1065 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1066 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1067 trace(
"padding %u position %u past stop #2\n", pad, (
UINT)
pos);
1069
1072 ok(
pos*1000/freq <= slept*1.1,
"Position %u too far after playing %ums\n", (
UINT)
pos, slept);
1073
1076 "Position %u after stop vs. %u padding\n", (
UINT)
pos, pad);
1078
1080
1081 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1082 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1084
1085
1086 hr = IAudioClient_Reset(ac);
1089
1090 hr = IAudioClient_Reset(ac);
1091 ok(
hr ==
S_OK,
"Reset on an already reset stream returns %08x\n",
hr);
1092
1093 hr = IAudioClock_GetPosition(acl, &
pos, &pcpos);
1094 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1095 ok(
pos == 0,
"GetPosition returned non-zero pos after Reset\n");
1096 ok(pcpos > pcpos0,
"pcpos should increase\n");
1097
1099 hr = IAudioRenderClient_GetBuffer(arc,
avail, &
data);
1100 ok(
hr ==
S_OK,
"GetBuffer failed: %08x\n",
hr);
1102
1105 ok(
hr ==
S_OK,
"ReleaseBuffer failed: %08x\n",
hr);
1107
1108 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1109 ok(
hr ==
S_OK,
"GetCurrentPadding failed: %08x\n",
hr);
1110 ok(pad ==
sum,
"padding %u prior to start\n", pad);
1111
1112 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1113 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1114 ok(
pos == 0,
"GetPosition returned non-zero pos after Reset\n");
1116
1117 hr = IAudioClient_Start(ac);
1119
1121 slept += 100;
1122
1123 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1124 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1125 trace(
"position %u past %ums sleep #3\n", (
UINT)
pos, slept);
1129 ok(
pos*1000/freq <= slept*1.1,
"Position %u too far after playing %ums\n", (
UINT)
pos, slept);
1130 else
1131 skip(
"Rerun with WINETEST_DEBUG=2 for GetPosition tests.\n");
1133
1134 hr = IAudioClient_Reset(ac);
1135 ok(
hr == AUDCLNT_E_NOT_STOPPED,
"Reset while playing: %08x\n",
hr);
1136
1137 hr = IAudioClient_Stop(ac);
1139
1140 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1141 ok(
hr ==
S_OK,
"GetCurrentPadding failed: %08x\n",
hr);
1142
1143 hr = IAudioClock_GetPosition(acl, &
pos, &pcpos);
1144 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1145 trace(
"padding %u position %u past stop #3\n", pad, (
UINT)
pos);
1147 ok(pcpos > pcpos0,
"pcpos should increase\n");
1150 ok(
pos*1000/freq <= slept*1.1,
"Position %u too far after stop %ums\n", (
UINT)
pos, slept);
1153 "Position %u after stop vs. %u padding\n", (
UINT)
pos, pad);
1155
1156
1157 hr = IAudioClient_Reset(ac);
1160 pcpos0 = pcpos;
1161
1163
1164 hr = IAudioClient_Reset(ac);
1165 ok(
hr ==
S_OK,
"Reset on an already reset stream returns %08x\n",
hr);
1166
1167 hr = IAudioClient_Start(ac);
1169
1172 hr = IAudioRenderClient_GetBuffer(arc,
avail, &
data);
1173 ok(
hr ==
S_OK,
"GetBuffer failed: %08x\n",
hr);
1175
1177 hr = IAudioClient_Stop(ac);
1179
1181 slept += 20;
1182
1183 hr = IAudioClient_Reset(ac);
1184 ok(
hr == AUDCLNT_E_BUFFER_OPERATION_PENDING,
"Reset failed: %08x\n",
hr);
1185
1186 hr = IAudioClient_Start(ac);
1188 }
1189
1190
1191 hr = IAudioRenderClient_ReleaseBuffer(arc,
avail,
1193 ok(
hr ==
S_OK,
"ReleaseBuffer after stop+start failed: %08x\n",
hr);
1195
1196
1197
1198
1199
1200
1201
1202
1204 slept += 350;
1206 trace(
"hpctime %u after %ums\n",
1208
1209 hr = IAudioClock_GetPosition(acl, &
pos, &pcpos);
1210 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1213
1214 for(
i=0;
i < 9;
i++) {
1216 slept += 100;
1217
1218 hr = IAudioClock_GetPosition(acl, &
pos, &pcpos);
1219 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1220
1221 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1222 ok(
hr ==
S_OK,
"GetCurrentPadding failed: %08x\n",
hr);
1223
1225 trace(
"hpctime %u pcpos %u\n",
1227 (
ULONG)((pcpos-pcpos0)/10000));
1228
1229
1230 trace(
"padding %u position %u/%u slept %ums iteration %d\n", pad, (
UINT)
pos,
sum-pad, slept,
i);
1231 ok(pad ?
pos >
last :
pos >=
last,
"No position increase at iteration %d\n",
i);
1234
1236 ok(
pos*1000/freq <= slept*1.1,
"Position %u too far after %ums\n", (
UINT)
pos, slept);
1237 if (pad)
1239 "Position delta %ld not regular: %ld ms\n", (
long)(
pos-
last), (
long)((
pos-
last)*1000/freq));
1240 }
1242
1243 hr = IAudioClient_GetStreamLatency(ac, &t1);
1244 ok(
hr ==
S_OK,
"GetStreamLatency failed: %08x\n",
hr);
1245 ok(t1 == t2,
"Latency not constant, delta %ld\n", (
long)(t1-t2));
1246
1249 hr = IAudioRenderClient_GetBuffer(arc,
avail, &
data);
1250
1251 ok(
hr ==
S_OK ||
hr == AUDCLNT_E_BUFFER_TOO_LARGE,
1252 "GetBuffer large (%u) failed: %08x\n",
avail,
hr);
1254
1255
1256
1257
1260 } else {
1261 avail = gbsize - pad;
1262 hr = IAudioRenderClient_GetBuffer(arc,
avail, &
data);
1265 }
1269 hr = IAudioRenderClient_ReleaseBuffer(arc,
avail, 0);
1270 } else {
1271 hr = IAudioRenderClient_ReleaseBuffer(arc,
avail,
1273 }
1274 ok(
hr ==
S_OK,
"ReleaseBuffer failed: %08x\n",
hr);
1276 }
1277
1278 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1279 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1281
1283
1284 hr = IAudioClient_GetCurrentPadding(ac, &pad);
1285 ok(
hr ==
S_OK,
"GetCurrentPadding failed: %08x\n",
hr);
1286
1287 hr = IAudioClock_GetPosition(acl, &
pos,
NULL);
1288 ok(
hr ==
S_OK,
"GetPosition failed: %08x\n",
hr);
1289 trace(
"position %u past underrun, %u padding left, %u frames written\n", (
UINT)
pos, pad,
sum);
1290
1291 if (share) {
1292
1293 ok(pad == 0,
"GetCurrentPadding returned %u, should be 0\n", pad);
1295 "Position %u at end vs. %u submitted frames\n", (
UINT)
pos,
sum);
1296 } else {
1297
1299 pos * pwfx->
nSamplesPerSec == (
sum-pad) * freq,
"GetCurrentPadding returned %u, should be 0\n", pad);
1300
1303 "Position %u at end vs. %u submitted frames\n", (
UINT)
pos,
sum);
1304 }
1305
1306 hr = IAudioClient_GetStreamLatency(ac, &t1);
1307 ok(
hr ==
S_OK,
"GetStreamLatency failed: %08x\n",
hr);
1308 ok(t1 == t2,
"Latency not constant, delta %ld\n", (
long)(t1-t2));
1309
1312
1313 hr = IAudioClient_Stop(ac);
1315
1317
1318 IAudioClock_Release(acl);
1319 IAudioRenderClient_Release(arc);
1320 IAudioClient_Release(ac);
1321}
std::map< E_STRING, PART_TEST > parts
unsigned long long UINT64
@ AUDCLNT_BUFFERFLAGS_SILENT
BOOL WINAPI QueryPerformanceFrequency(OUT PLARGE_INTEGER lpFrequency)
BOOL WINAPI QueryPerformanceCounter(OUT PLARGE_INTEGER lpPerformanceCount)
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLenum GLuint GLsizei bufsize
static DWORD wave_generate_tone(PWAVEFORMATEX pwfx, BYTE *data, UINT32 frames)
INT WINAPI MulDiv(INT nNumber, INT nNumerator, INT nDenominator)
static int sum(int x_, int y_)
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)