testautomation_audio.c 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544
  1. /**
  2. * Original code: automated SDL audio test written by Edgar Simo "bobbens"
  3. * New/updated tests: aschiffler at ferzkopp dot net
  4. */
  5. /* quiet windows compiler warnings */
  6. #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
  7. #define _CRT_SECURE_NO_WARNINGS
  8. #endif
  9. #include <math.h>
  10. #include <stdio.h>
  11. #include <SDL3/SDL.h>
  12. #include <SDL3/SDL_test.h>
  13. #include "testautomation_suites.h"
  14. /* ================= Test Case Implementation ================== */
  15. /* Fixture */
  16. static void SDLCALL audioSetUp(void **arg)
  17. {
  18. /* Start SDL audio subsystem */
  19. bool ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
  20. SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO)");
  21. SDLTest_AssertCheck(ret == true, "Check result from SDL_InitSubSystem(SDL_INIT_AUDIO)");
  22. if (!ret) {
  23. SDLTest_LogError("%s", SDL_GetError());
  24. }
  25. }
  26. static void SDLCALL audioTearDown(void *arg)
  27. {
  28. /* Remove a possibly created file from SDL disk writer audio driver; ignore errors */
  29. (void)remove("sdlaudio.raw");
  30. SDLTest_AssertPass("Cleanup of test files completed");
  31. }
  32. #if 0 /* !!! FIXME: maybe update this? */
  33. /* Global counter for callback invocation */
  34. static int g_audio_testCallbackCounter;
  35. /* Global accumulator for total callback length */
  36. static int g_audio_testCallbackLength;
  37. /* Test callback function */
  38. static void SDLCALL audio_testCallback(void *userdata, Uint8 *stream, int len)
  39. {
  40. /* track that callback was called */
  41. g_audio_testCallbackCounter++;
  42. g_audio_testCallbackLength += len;
  43. }
  44. #endif
  45. static SDL_AudioDeviceID g_audio_id = 0;
  46. /* Test case functions */
  47. /**
  48. * Stop and restart audio subsystem
  49. *
  50. * \sa SDL_QuitSubSystem
  51. * \sa SDL_InitSubSystem
  52. */
  53. static int SDLCALL audio_quitInitAudioSubSystem(void *arg)
  54. {
  55. /* Stop SDL audio subsystem */
  56. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  57. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  58. /* Restart audio again */
  59. audioSetUp(NULL);
  60. return TEST_COMPLETED;
  61. }
  62. /**
  63. * Start and stop audio directly
  64. *
  65. * \sa SDL_InitAudio
  66. * \sa SDL_QuitAudio
  67. */
  68. static int SDLCALL audio_initQuitAudio(void *arg)
  69. {
  70. int result;
  71. int i, iMax;
  72. const char *audioDriver;
  73. const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DRIVER);
  74. /* Stop SDL audio subsystem */
  75. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  76. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  77. /* Loop over all available audio drivers */
  78. iMax = SDL_GetNumAudioDrivers();
  79. SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
  80. SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
  81. for (i = 0; i < iMax; i++) {
  82. audioDriver = SDL_GetAudioDriver(i);
  83. SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
  84. SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
  85. SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
  86. if (hint && SDL_strcmp(audioDriver, hint) != 0) {
  87. continue;
  88. }
  89. /* Call Init */
  90. SDL_SetHint(SDL_HINT_AUDIO_DRIVER, audioDriver);
  91. result = SDL_InitSubSystem(SDL_INIT_AUDIO);
  92. SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO) with driver='%s'", audioDriver);
  93. SDLTest_AssertCheck(result == true, "Validate result value; expected: true got: %d", result);
  94. /* Call Quit */
  95. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  96. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  97. }
  98. /* NULL driver specification */
  99. audioDriver = NULL;
  100. /* Call Init */
  101. SDL_SetHint(SDL_HINT_AUDIO_DRIVER, audioDriver);
  102. result = SDL_InitSubSystem(SDL_INIT_AUDIO);
  103. SDLTest_AssertPass("Call to SDL_AudioInit(NULL)");
  104. SDLTest_AssertCheck(result == true, "Validate result value; expected: true got: %d", result);
  105. /* Call Quit */
  106. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  107. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  108. /* Restart audio again */
  109. audioSetUp(NULL);
  110. return TEST_COMPLETED;
  111. }
  112. /**
  113. * Start, open, close and stop audio
  114. *
  115. * \sa SDL_InitAudio
  116. * \sa SDL_OpenAudioDevice
  117. * \sa SDL_CloseAudioDevice
  118. * \sa SDL_QuitAudio
  119. */
  120. static int SDLCALL audio_initOpenCloseQuitAudio(void *arg)
  121. {
  122. int result;
  123. int i, iMax, j, k;
  124. const char *audioDriver;
  125. SDL_AudioSpec desired;
  126. const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DRIVER);
  127. /* Stop SDL audio subsystem */
  128. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  129. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  130. /* Loop over all available audio drivers */
  131. iMax = SDL_GetNumAudioDrivers();
  132. SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
  133. SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
  134. for (i = 0; i < iMax; i++) {
  135. audioDriver = SDL_GetAudioDriver(i);
  136. SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
  137. SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
  138. SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
  139. if (hint && SDL_strcmp(audioDriver, hint) != 0) {
  140. continue;
  141. }
  142. /* Change specs */
  143. for (j = 0; j < 2; j++) {
  144. /* Call Init */
  145. SDL_SetHint(SDL_HINT_AUDIO_DRIVER, audioDriver);
  146. result = SDL_InitSubSystem(SDL_INIT_AUDIO);
  147. SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO) with driver='%s'", audioDriver);
  148. SDLTest_AssertCheck(result == true, "Validate result value; expected: true got: %d", result);
  149. /* Set spec */
  150. SDL_zero(desired);
  151. switch (j) {
  152. case 0:
  153. /* Set standard desired spec */
  154. desired.freq = 22050;
  155. desired.format = SDL_AUDIO_S16;
  156. desired.channels = 2;
  157. break;
  158. case 1:
  159. /* Set custom desired spec */
  160. desired.freq = 48000;
  161. desired.format = SDL_AUDIO_F32;
  162. desired.channels = 2;
  163. break;
  164. }
  165. /* Call Open (maybe multiple times) */
  166. for (k = 0; k <= j; k++) {
  167. result = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &desired);
  168. if (k == 0) {
  169. g_audio_id = result;
  170. }
  171. SDLTest_AssertPass("Call to SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, desired_spec_%d), call %d", j, k + 1);
  172. SDLTest_AssertCheck(result > 0, "Verify return value; expected: > 0, got: %d", result);
  173. }
  174. /* Call Close (maybe multiple times) */
  175. for (k = 0; k <= j; k++) {
  176. SDL_CloseAudioDevice(g_audio_id);
  177. SDLTest_AssertPass("Call to SDL_CloseAudioDevice(), call %d", k + 1);
  178. }
  179. /* Call Quit (maybe multiple times) */
  180. for (k = 0; k <= j; k++) {
  181. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  182. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO), call %d", k + 1);
  183. }
  184. } /* spec loop */
  185. } /* driver loop */
  186. /* Restart audio again */
  187. audioSetUp(NULL);
  188. return TEST_COMPLETED;
  189. }
  190. /**
  191. * Pause and unpause audio
  192. *
  193. * \sa SDL_PauseAudioDevice
  194. * \sa SDL_PlayAudioDevice
  195. */
  196. static int SDLCALL audio_pauseUnpauseAudio(void *arg)
  197. {
  198. int iMax;
  199. int i, j /*, k, l*/;
  200. int result;
  201. const char *audioDriver;
  202. SDL_AudioSpec desired;
  203. const char *hint = SDL_GetHint(SDL_HINT_AUDIO_DRIVER);
  204. /* Stop SDL audio subsystem */
  205. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  206. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  207. /* Loop over all available audio drivers */
  208. iMax = SDL_GetNumAudioDrivers();
  209. SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
  210. SDLTest_AssertCheck(iMax > 0, "Validate number of audio drivers; expected: >0 got: %d", iMax);
  211. for (i = 0; i < iMax; i++) {
  212. audioDriver = SDL_GetAudioDriver(i);
  213. SDLTest_AssertPass("Call to SDL_GetAudioDriver(%d)", i);
  214. SDLTest_Assert(audioDriver != NULL, "Audio driver name is not NULL");
  215. SDLTest_AssertCheck(audioDriver[0] != '\0', "Audio driver name is not empty; got: %s", audioDriver); /* NOLINT(clang-analyzer-core.NullDereference): Checked for NULL above */
  216. if (hint && SDL_strcmp(audioDriver, hint) != 0) {
  217. continue;
  218. }
  219. /* Change specs */
  220. for (j = 0; j < 2; j++) {
  221. /* Call Init */
  222. SDL_SetHint(SDL_HINT_AUDIO_DRIVER, audioDriver);
  223. result = SDL_InitSubSystem(SDL_INIT_AUDIO);
  224. SDLTest_AssertPass("Call to SDL_InitSubSystem(SDL_INIT_AUDIO) with driver='%s'", audioDriver);
  225. SDLTest_AssertCheck(result == true, "Validate result value; expected: true got: %d", result);
  226. /* Set spec */
  227. SDL_zero(desired);
  228. switch (j) {
  229. case 0:
  230. /* Set standard desired spec */
  231. desired.freq = 22050;
  232. desired.format = SDL_AUDIO_S16;
  233. desired.channels = 2;
  234. break;
  235. case 1:
  236. /* Set custom desired spec */
  237. desired.freq = 48000;
  238. desired.format = SDL_AUDIO_F32;
  239. desired.channels = 2;
  240. break;
  241. }
  242. /* Call Open */
  243. g_audio_id = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &desired);
  244. result = g_audio_id;
  245. SDLTest_AssertPass("Call to SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, desired_spec_%d)", j);
  246. SDLTest_AssertCheck(result > 0, "Verify return value; expected > 0 got: %d", result);
  247. #if 0 /* !!! FIXME: maybe update this? */
  248. /* Start and stop audio multiple times */
  249. for (l = 0; l < 3; l++) {
  250. SDLTest_Log("Pause/Unpause iteration: %d", l + 1);
  251. /* Reset callback counters */
  252. g_audio_testCallbackCounter = 0;
  253. g_audio_testCallbackLength = 0;
  254. /* Un-pause audio to start playing (maybe multiple times) */
  255. for (k = 0; k <= j; k++) {
  256. SDL_PlayAudioDevice(g_audio_id);
  257. SDLTest_AssertPass("Call to SDL_PlayAudioDevice(g_audio_id), call %d", k + 1);
  258. }
  259. /* Wait for callback */
  260. int totalDelay = 0;
  261. do {
  262. SDL_Delay(10);
  263. totalDelay += 10;
  264. } while (g_audio_testCallbackCounter == 0 && totalDelay < 1000);
  265. SDLTest_AssertCheck(g_audio_testCallbackCounter > 0, "Verify callback counter; expected: >0 got: %d", g_audio_testCallbackCounter);
  266. SDLTest_AssertCheck(g_audio_testCallbackLength > 0, "Verify callback length; expected: >0 got: %d", g_audio_testCallbackLength);
  267. /* Pause audio to stop playing (maybe multiple times) */
  268. for (k = 0; k <= j; k++) {
  269. const int pause_on = (k == 0) ? 1 : SDLTest_RandomIntegerInRange(99, 9999);
  270. if (pause_on) {
  271. SDL_PauseAudioDevice(g_audio_id);
  272. SDLTest_AssertPass("Call to SDL_PauseAudioDevice(g_audio_id), call %d", k + 1);
  273. } else {
  274. SDL_PlayAudioDevice(g_audio_id);
  275. SDLTest_AssertPass("Call to SDL_PlayAudioDevice(g_audio_id), call %d", k + 1);
  276. }
  277. }
  278. /* Ensure callback is not called again */
  279. const int originalCounter = g_audio_testCallbackCounter;
  280. SDL_Delay(totalDelay + 10);
  281. SDLTest_AssertCheck(originalCounter == g_audio_testCallbackCounter, "Verify callback counter; expected: %d, got: %d", originalCounter, g_audio_testCallbackCounter);
  282. }
  283. #endif
  284. /* Call Close */
  285. SDL_CloseAudioDevice(g_audio_id);
  286. SDLTest_AssertPass("Call to SDL_CloseAudioDevice()");
  287. /* Call Quit */
  288. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  289. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  290. } /* spec loop */
  291. } /* driver loop */
  292. /* Restart audio again */
  293. audioSetUp(NULL);
  294. return TEST_COMPLETED;
  295. }
  296. /**
  297. * Enumerate and name available audio devices (playback and recording).
  298. *
  299. * \sa SDL_GetNumAudioDevices
  300. * \sa SDL_GetAudioDeviceName
  301. */
  302. static int SDLCALL audio_enumerateAndNameAudioDevices(void *arg)
  303. {
  304. int t;
  305. int i, n;
  306. const char *name;
  307. SDL_AudioDeviceID *devices;
  308. /* Iterate over types: t=0 playback device, t=1 recording device */
  309. for (t = 0; t < 2; t++) {
  310. /* Get number of devices. */
  311. devices = (t) ? SDL_GetAudioRecordingDevices(&n) : SDL_GetAudioPlaybackDevices(&n);
  312. SDLTest_AssertPass("Call to SDL_GetAudio%sDevices(%i)", (t) ? "Recording" : "Playback", t);
  313. SDLTest_Log("Number of %s devices < 0, reported as %i", (t) ? "recording" : "playback", n);
  314. SDLTest_AssertCheck(n >= 0, "Validate result is >= 0, got: %i", n);
  315. /* List devices. */
  316. if (n > 0) {
  317. SDLTest_AssertCheck(devices != NULL, "Validate devices is not NULL if n > 0");
  318. for (i = 0; i < n; i++) {
  319. name = SDL_GetAudioDeviceName(devices[i]);
  320. SDLTest_AssertPass("Call to SDL_GetAudioDeviceName(%i)", i);
  321. SDLTest_AssertCheck(name != NULL, "Verify result from SDL_GetAudioDeviceName(%i) is not NULL", i);
  322. if (name != NULL) {
  323. SDLTest_AssertCheck(name[0] != '\0', "verify result from SDL_GetAudioDeviceName(%i) is not empty, got: '%s'", i, name);
  324. }
  325. }
  326. }
  327. SDL_free(devices);
  328. }
  329. return TEST_COMPLETED;
  330. }
  331. /**
  332. * Negative tests around enumeration and naming of audio devices.
  333. *
  334. * \sa SDL_GetNumAudioDevices
  335. * \sa SDL_GetAudioDeviceName
  336. */
  337. static int SDLCALL audio_enumerateAndNameAudioDevicesNegativeTests(void *arg)
  338. {
  339. return TEST_COMPLETED; /* nothing in here atm since these interfaces changed in SDL3. */
  340. }
  341. /**
  342. * Checks available audio driver names.
  343. *
  344. * \sa SDL_GetNumAudioDrivers
  345. * \sa SDL_GetAudioDriver
  346. */
  347. static int SDLCALL audio_printAudioDrivers(void *arg)
  348. {
  349. int i, n;
  350. const char *name;
  351. /* Get number of drivers */
  352. n = SDL_GetNumAudioDrivers();
  353. SDLTest_AssertPass("Call to SDL_GetNumAudioDrivers()");
  354. SDLTest_AssertCheck(n >= 0, "Verify number of audio drivers >= 0, got: %i", n);
  355. /* List drivers. */
  356. if (n > 0) {
  357. for (i = 0; i < n; i++) {
  358. name = SDL_GetAudioDriver(i);
  359. SDLTest_AssertPass("Call to SDL_GetAudioDriver(%i)", i);
  360. SDLTest_AssertCheck(name != NULL, "Verify returned name is not NULL");
  361. if (name != NULL) {
  362. SDLTest_AssertCheck(name[0] != '\0', "Verify returned name is not empty, got: '%s'", name);
  363. }
  364. }
  365. }
  366. return TEST_COMPLETED;
  367. }
  368. /**
  369. * Checks current audio driver name with initialized audio.
  370. *
  371. * \sa SDL_GetCurrentAudioDriver
  372. */
  373. static int SDLCALL audio_printCurrentAudioDriver(void *arg)
  374. {
  375. /* Check current audio driver */
  376. const char *name = SDL_GetCurrentAudioDriver();
  377. SDLTest_AssertPass("Call to SDL_GetCurrentAudioDriver()");
  378. SDLTest_AssertCheck(name != NULL, "Verify returned name is not NULL");
  379. if (name != NULL) {
  380. SDLTest_AssertCheck(name[0] != '\0', "Verify returned name is not empty, got: '%s'", name);
  381. }
  382. return TEST_COMPLETED;
  383. }
  384. /* Definition of all formats, channels, and frequencies used to test audio conversions */
  385. static SDL_AudioFormat g_audioFormats[] = {
  386. SDL_AUDIO_S8, SDL_AUDIO_U8,
  387. SDL_AUDIO_S16LE, SDL_AUDIO_S16BE,
  388. SDL_AUDIO_S32LE, SDL_AUDIO_S32BE,
  389. SDL_AUDIO_F32LE, SDL_AUDIO_F32BE
  390. };
  391. static const char *g_audioFormatsVerbose[] = {
  392. "SDL_AUDIO_S8", "SDL_AUDIO_U8",
  393. "SDL_AUDIO_S16LE", "SDL_AUDIO_S16BE",
  394. "SDL_AUDIO_S32LE", "SDL_AUDIO_S32BE",
  395. "SDL_AUDIO_F32LE", "SDL_AUDIO_F32BE"
  396. };
  397. static SDL_AudioFormat g_invalidAudioFormats[] = {
  398. (SDL_AudioFormat)SDL_DEFINE_AUDIO_FORMAT(SDL_AUDIO_MASK_SIGNED, SDL_AUDIO_MASK_BIG_ENDIAN, SDL_AUDIO_MASK_FLOAT, SDL_AUDIO_MASK_BITSIZE)
  399. };
  400. static const char *g_invalidAudioFormatsVerbose[] = {
  401. "SDL_AUDIO_UNKNOWN"
  402. };
  403. static const int g_numAudioFormats = SDL_arraysize(g_audioFormats);
  404. static const int g_numInvalidAudioFormats = SDL_arraysize(g_invalidAudioFormats);
  405. static Uint8 g_audioChannels[] = { 1, 2, 4, 6 };
  406. static const int g_numAudioChannels = SDL_arraysize(g_audioChannels);
  407. static int g_audioFrequencies[] = { 11025, 22050, 44100, 48000 };
  408. static const int g_numAudioFrequencies = SDL_arraysize(g_audioFrequencies);
  409. /* Verify the audio formats are laid out as expected */
  410. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_U8_FORMAT, SDL_AUDIO_U8 == SDL_AUDIO_BITSIZE(8));
  411. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S8_FORMAT, SDL_AUDIO_S8 == (SDL_AUDIO_BITSIZE(8) | SDL_AUDIO_MASK_SIGNED));
  412. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S16LE_FORMAT, SDL_AUDIO_S16LE == (SDL_AUDIO_BITSIZE(16) | SDL_AUDIO_MASK_SIGNED));
  413. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S16BE_FORMAT, SDL_AUDIO_S16BE == (SDL_AUDIO_S16LE | SDL_AUDIO_MASK_BIG_ENDIAN));
  414. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S32LE_FORMAT, SDL_AUDIO_S32LE == (SDL_AUDIO_BITSIZE(32) | SDL_AUDIO_MASK_SIGNED));
  415. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_S32BE_FORMAT, SDL_AUDIO_S32BE == (SDL_AUDIO_S32LE | SDL_AUDIO_MASK_BIG_ENDIAN));
  416. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_F32LE_FORMAT, SDL_AUDIO_F32LE == (SDL_AUDIO_BITSIZE(32) | SDL_AUDIO_MASK_FLOAT | SDL_AUDIO_MASK_SIGNED));
  417. SDL_COMPILE_TIME_ASSERT(SDL_AUDIO_F32BE_FORMAT, SDL_AUDIO_F32BE == (SDL_AUDIO_F32LE | SDL_AUDIO_MASK_BIG_ENDIAN));
  418. /**
  419. * Call to SDL_GetAudioFormatName
  420. *
  421. * \sa SDL_GetAudioFormatName
  422. */
  423. static int SDLCALL audio_getAudioFormatName(void *arg)
  424. {
  425. const char *error;
  426. int i;
  427. SDL_AudioFormat format;
  428. const char *result;
  429. /* audio formats */
  430. for (i = 0; i < g_numAudioFormats; i++) {
  431. format = g_audioFormats[i];
  432. SDLTest_Log("Audio Format: %s (%d)", g_audioFormatsVerbose[i], format);
  433. /* Get name of format */
  434. result = SDL_GetAudioFormatName(format);
  435. SDLTest_AssertPass("Call to SDL_GetAudioFormatName()");
  436. SDLTest_AssertCheck(result != NULL, "Verify result is not NULL");
  437. if (result != NULL) {
  438. SDLTest_AssertCheck(result[0] != '\0', "Verify result is non-empty");
  439. SDLTest_AssertCheck(SDL_strcmp(result, g_audioFormatsVerbose[i]) == 0,
  440. "Verify result text; expected: %s, got %s", g_audioFormatsVerbose[i], result);
  441. }
  442. }
  443. /* Negative cases */
  444. /* Invalid Formats */
  445. SDL_ClearError();
  446. SDLTest_AssertPass("Call to SDL_ClearError()");
  447. for (i = 0; i < g_numInvalidAudioFormats; i++) {
  448. format = g_invalidAudioFormats[i];
  449. result = SDL_GetAudioFormatName(format);
  450. SDLTest_AssertPass("Call to SDL_GetAudioFormatName(%d)", format);
  451. SDLTest_AssertCheck(result != NULL, "Verify result is not NULL");
  452. if (result != NULL) {
  453. SDLTest_AssertCheck(result[0] != '\0',
  454. "Verify result is non-empty; got: %s", result);
  455. SDLTest_AssertCheck(SDL_strcmp(result, g_invalidAudioFormatsVerbose[i]) == 0,
  456. "Validate name is UNKNOWN, expected: '%s', got: '%s'", g_invalidAudioFormatsVerbose[i], result);
  457. }
  458. error = SDL_GetError();
  459. SDLTest_AssertPass("Call to SDL_GetError()");
  460. SDLTest_AssertCheck(error == NULL || error[0] == '\0', "Validate that error message is empty");
  461. }
  462. return TEST_COMPLETED;
  463. }
  464. /**
  465. * Builds various audio conversion structures
  466. *
  467. * \sa SDL_CreateAudioStream
  468. */
  469. static int SDLCALL audio_buildAudioStream(void *arg)
  470. {
  471. SDL_AudioStream *stream;
  472. SDL_AudioSpec spec1;
  473. SDL_AudioSpec spec2;
  474. int i, ii, j, jj, k, kk;
  475. SDL_zero(spec1);
  476. SDL_zero(spec2);
  477. /* Call Quit */
  478. SDL_QuitSubSystem(SDL_INIT_AUDIO);
  479. SDLTest_AssertPass("Call to SDL_QuitSubSystem(SDL_INIT_AUDIO)");
  480. /* No conversion needed */
  481. spec1.format = SDL_AUDIO_S16LE;
  482. spec1.channels = 2;
  483. spec1.freq = 22050;
  484. stream = SDL_CreateAudioStream(&spec1, &spec1);
  485. SDLTest_AssertPass("Call to SDL_CreateAudioStream(spec1 ==> spec1)");
  486. SDLTest_AssertCheck(stream != NULL, "Verify stream value; expected: != NULL, got: %p", stream);
  487. SDL_DestroyAudioStream(stream);
  488. /* Typical conversion */
  489. spec1.format = SDL_AUDIO_S8;
  490. spec1.channels = 1;
  491. spec1.freq = 22050;
  492. spec2.format = SDL_AUDIO_S16LE;
  493. spec2.channels = 2;
  494. spec2.freq = 44100;
  495. stream = SDL_CreateAudioStream(&spec1, &spec2);
  496. SDLTest_AssertPass("Call to SDL_CreateAudioStream(spec1 ==> spec2)");
  497. SDLTest_AssertCheck(stream != NULL, "Verify stream value; expected: != NULL, got: %p", stream);
  498. SDL_DestroyAudioStream(stream);
  499. /* All source conversions with random conversion targets, allow 'null' conversions */
  500. for (i = 0; i < g_numAudioFormats; i++) {
  501. for (j = 0; j < g_numAudioChannels; j++) {
  502. for (k = 0; k < g_numAudioFrequencies; k++) {
  503. spec1.format = g_audioFormats[i];
  504. spec1.channels = g_audioChannels[j];
  505. spec1.freq = g_audioFrequencies[k];
  506. ii = SDLTest_RandomIntegerInRange(0, g_numAudioFormats - 1);
  507. jj = SDLTest_RandomIntegerInRange(0, g_numAudioChannels - 1);
  508. kk = SDLTest_RandomIntegerInRange(0, g_numAudioFrequencies - 1);
  509. spec2.format = g_audioFormats[ii];
  510. spec2.channels = g_audioChannels[jj];
  511. spec2.freq = g_audioFrequencies[kk];
  512. stream = SDL_CreateAudioStream(&spec1, &spec2);
  513. SDLTest_AssertPass("Call to SDL_CreateAudioStream(format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i ==> format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i)",
  514. i, g_audioFormatsVerbose[i], spec1.format, j, spec1.channels, k, spec1.freq, ii, g_audioFormatsVerbose[ii], spec2.format, jj, spec2.channels, kk, spec2.freq);
  515. SDLTest_AssertCheck(stream != NULL, "Verify stream value; expected: != NULL, got: %p", stream);
  516. if (stream == NULL) {
  517. SDLTest_LogError("%s", SDL_GetError());
  518. }
  519. SDL_DestroyAudioStream(stream);
  520. }
  521. }
  522. }
  523. /* Restart audio again */
  524. audioSetUp(NULL);
  525. return TEST_COMPLETED;
  526. }
  527. /**
  528. * Checks calls with invalid input to SDL_CreateAudioStream
  529. *
  530. * \sa SDL_CreateAudioStream
  531. */
  532. static int SDLCALL audio_buildAudioStreamNegative(void *arg)
  533. {
  534. const char *error;
  535. SDL_AudioStream *stream;
  536. SDL_AudioSpec spec1;
  537. SDL_AudioSpec spec2;
  538. int i;
  539. char message[256];
  540. SDL_zero(spec1);
  541. SDL_zero(spec2);
  542. /* Valid format */
  543. spec1.format = SDL_AUDIO_S8;
  544. spec1.channels = 1;
  545. spec1.freq = 22050;
  546. spec2.format = SDL_AUDIO_S16LE;
  547. spec2.channels = 2;
  548. spec2.freq = 44100;
  549. SDL_ClearError();
  550. SDLTest_AssertPass("Call to SDL_ClearError()");
  551. /* Invalid conversions */
  552. for (i = 1; i < 64; i++) {
  553. /* Valid format to start with */
  554. spec1.format = SDL_AUDIO_S8;
  555. spec1.channels = 1;
  556. spec1.freq = 22050;
  557. spec2.format = SDL_AUDIO_S16LE;
  558. spec2.channels = 2;
  559. spec2.freq = 44100;
  560. SDL_ClearError();
  561. SDLTest_AssertPass("Call to SDL_ClearError()");
  562. /* Set various invalid format inputs */
  563. SDL_strlcpy(message, "Invalid: ", 256);
  564. if (i & 1) {
  565. SDL_strlcat(message, " spec1.format", 256);
  566. spec1.format = 0;
  567. }
  568. if (i & 2) {
  569. SDL_strlcat(message, " spec1.channels", 256);
  570. spec1.channels = 0;
  571. }
  572. if (i & 4) {
  573. SDL_strlcat(message, " spec1.freq", 256);
  574. spec1.freq = 0;
  575. }
  576. if (i & 8) {
  577. SDL_strlcat(message, " spec2.format", 256);
  578. spec2.format = 0;
  579. }
  580. if (i & 16) {
  581. SDL_strlcat(message, " spec2.channels", 256);
  582. spec2.channels = 0;
  583. }
  584. if (i & 32) {
  585. SDL_strlcat(message, " spec2.freq", 256);
  586. spec2.freq = 0;
  587. }
  588. SDLTest_Log("%s", message);
  589. stream = SDL_CreateAudioStream(&spec1, &spec2);
  590. SDLTest_AssertPass("Call to SDL_CreateAudioStream(spec1 ==> spec2)");
  591. SDLTest_AssertCheck(stream == NULL, "Verify stream value; expected: NULL, got: %p", stream);
  592. error = SDL_GetError();
  593. SDLTest_AssertPass("Call to SDL_GetError()");
  594. SDLTest_AssertCheck(error != NULL && error[0] != '\0', "Validate that error message was not NULL or empty");
  595. SDL_DestroyAudioStream(stream);
  596. }
  597. SDL_ClearError();
  598. SDLTest_AssertPass("Call to SDL_ClearError()");
  599. return TEST_COMPLETED;
  600. }
  601. /**
  602. * Checks current audio status.
  603. *
  604. * \sa SDL_GetAudioDeviceStatus
  605. */
  606. static int SDLCALL audio_getAudioStatus(void *arg)
  607. {
  608. return TEST_COMPLETED; /* no longer a thing in SDL3. */
  609. }
  610. /**
  611. * Opens, checks current audio status, and closes a device.
  612. *
  613. * \sa SDL_GetAudioStatus
  614. */
  615. static int SDLCALL audio_openCloseAndGetAudioStatus(void *arg)
  616. {
  617. return TEST_COMPLETED; /* not a thing in SDL3. */
  618. }
  619. /**
  620. * Locks and unlocks open audio device.
  621. *
  622. * \sa SDL_LockAudioDevice
  623. * \sa SDL_UnlockAudioDevice
  624. */
  625. static int SDLCALL audio_lockUnlockOpenAudioDevice(void *arg)
  626. {
  627. return TEST_COMPLETED; /* not a thing in SDL3 */
  628. }
  629. /**
  630. * Convert audio using various conversion structures
  631. *
  632. * \sa SDL_CreateAudioStream
  633. */
  634. static int SDLCALL audio_convertAudio(void *arg)
  635. {
  636. SDL_AudioStream *stream;
  637. SDL_AudioSpec spec1;
  638. SDL_AudioSpec spec2;
  639. int c;
  640. char message[128];
  641. int i, ii, j, jj, k, kk;
  642. SDL_zero(spec1);
  643. SDL_zero(spec2);
  644. /* Iterate over bitmask that determines which parameters are modified in the conversion */
  645. for (c = 1; c < 8; c++) {
  646. SDL_strlcpy(message, "Changing:", 128);
  647. if (c & 1) {
  648. SDL_strlcat(message, " Format", 128);
  649. }
  650. if (c & 2) {
  651. SDL_strlcat(message, " Channels", 128);
  652. }
  653. if (c & 4) {
  654. SDL_strlcat(message, " Frequencies", 128);
  655. }
  656. SDLTest_Log("%s", message);
  657. /* All source conversions with random conversion targets */
  658. for (i = 0; i < g_numAudioFormats; i++) {
  659. for (j = 0; j < g_numAudioChannels; j++) {
  660. for (k = 0; k < g_numAudioFrequencies; k++) {
  661. spec1.format = g_audioFormats[i];
  662. spec1.channels = g_audioChannels[j];
  663. spec1.freq = g_audioFrequencies[k];
  664. /* Ensure we have a different target format */
  665. do {
  666. if (c & 1) {
  667. ii = SDLTest_RandomIntegerInRange(0, g_numAudioFormats - 1);
  668. } else {
  669. ii = 1;
  670. }
  671. if (c & 2) {
  672. jj = SDLTest_RandomIntegerInRange(0, g_numAudioChannels - 1);
  673. } else {
  674. jj = j;
  675. }
  676. if (c & 4) {
  677. kk = SDLTest_RandomIntegerInRange(0, g_numAudioFrequencies - 1);
  678. } else {
  679. kk = k;
  680. }
  681. } while ((i == ii) && (j == jj) && (k == kk));
  682. spec2.format = g_audioFormats[ii];
  683. spec2.channels = g_audioChannels[jj];
  684. spec2.freq = g_audioFrequencies[kk];
  685. stream = SDL_CreateAudioStream(&spec1, &spec2);
  686. SDLTest_AssertPass("Call to SDL_CreateAudioStream(format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i ==> format[%i]=%s(%i),channels[%i]=%i,freq[%i]=%i)",
  687. i, g_audioFormatsVerbose[i], spec1.format, j, spec1.channels, k, spec1.freq, ii, g_audioFormatsVerbose[ii], spec2.format, jj, spec2.channels, kk, spec2.freq);
  688. SDLTest_AssertCheck(stream != NULL, "Verify stream value; expected: != NULL, got: %p", stream);
  689. if (stream == NULL) {
  690. SDLTest_LogError("%s", SDL_GetError());
  691. } else {
  692. Uint8 *dst_buf = NULL, *src_buf = NULL;
  693. int dst_len = 0, src_len = 0, real_dst_len = 0;
  694. int l = 64, m;
  695. int src_framesize, dst_framesize;
  696. int src_silence, dst_silence;
  697. src_framesize = SDL_AUDIO_FRAMESIZE(spec1);
  698. dst_framesize = SDL_AUDIO_FRAMESIZE(spec2);
  699. src_len = l * src_framesize;
  700. SDLTest_Log("Creating dummy sample buffer of %i length (%i bytes)", l, src_len);
  701. src_buf = (Uint8 *)SDL_malloc(src_len);
  702. SDLTest_AssertCheck(src_buf != NULL, "Check src data buffer to convert is not NULL");
  703. if (src_buf == NULL) {
  704. return TEST_ABORTED;
  705. }
  706. src_silence = SDL_GetSilenceValueForFormat(spec1.format);
  707. SDL_memset(src_buf, src_silence, src_len);
  708. dst_len = ((int)((((Sint64)l * spec2.freq) - 1) / spec1.freq) + 1) * dst_framesize;
  709. dst_buf = (Uint8 *)SDL_malloc(dst_len);
  710. SDLTest_AssertCheck(dst_buf != NULL, "Check dst data buffer to convert is not NULL");
  711. if (dst_buf == NULL) {
  712. return TEST_ABORTED;
  713. }
  714. real_dst_len = SDL_GetAudioStreamAvailable(stream);
  715. SDLTest_AssertCheck(0 == real_dst_len, "Verify available (pre-put); expected: %i; got: %i", 0, real_dst_len);
  716. /* Run the audio converter */
  717. if (!SDL_PutAudioStreamData(stream, src_buf, src_len) ||
  718. !SDL_FlushAudioStream(stream)) {
  719. return TEST_ABORTED;
  720. }
  721. real_dst_len = SDL_GetAudioStreamAvailable(stream);
  722. SDLTest_AssertCheck(dst_len == real_dst_len, "Verify available (post-put); expected: %i; got: %i", dst_len, real_dst_len);
  723. real_dst_len = SDL_GetAudioStreamData(stream, dst_buf, dst_len);
  724. SDLTest_AssertCheck(dst_len == real_dst_len, "Verify result value; expected: %i; got: %i", dst_len, real_dst_len);
  725. if (dst_len != real_dst_len) {
  726. return TEST_ABORTED;
  727. }
  728. real_dst_len = SDL_GetAudioStreamAvailable(stream);
  729. SDLTest_AssertCheck(0 == real_dst_len, "Verify available (post-get); expected: %i; got: %i", 0, real_dst_len);
  730. dst_silence = SDL_GetSilenceValueForFormat(spec2.format);
  731. for (m = 0; m < dst_len; ++m) {
  732. if (dst_buf[m] != dst_silence) {
  733. SDLTest_LogError("Output buffer is not silent");
  734. return TEST_ABORTED;
  735. }
  736. }
  737. SDL_DestroyAudioStream(stream);
  738. /* Free converted buffer */
  739. SDL_free(src_buf);
  740. SDL_free(dst_buf);
  741. }
  742. }
  743. }
  744. }
  745. }
  746. return TEST_COMPLETED;
  747. }
  748. /**
  749. * Opens, checks current connected status, and closes a device.
  750. *
  751. * \sa SDL_AudioDeviceConnected
  752. */
  753. static int SDLCALL audio_openCloseAudioDeviceConnected(void *arg)
  754. {
  755. return TEST_COMPLETED; /* not a thing in SDL3. */
  756. }
  757. static double sine_wave_sample(const Sint64 idx, const Sint64 rate, const Sint64 freq, const double phase)
  758. {
  759. /* Using integer modulo to avoid precision loss caused by large floating
  760. * point numbers. Sint64 is needed for the large integer multiplication.
  761. * The integers are assumed to be non-negative so that modulo is always
  762. * non-negative.
  763. * sin(i / rate * freq * 2 * PI + phase)
  764. * = sin(mod(i / rate * freq, 1) * 2 * PI + phase)
  765. * = sin(mod(i * freq, rate) / rate * 2 * PI + phase) */
  766. return SDL_sin(((double)(idx * freq % rate)) / ((double)rate) * (SDL_PI_D * 2) + phase);
  767. }
  768. /* Split the data into randomly sized chunks */
  769. static int put_audio_data_split(SDL_AudioStream* stream, const void* buf, int len)
  770. {
  771. SDL_AudioSpec spec;
  772. int frame_size;
  773. int ret = SDL_GetAudioStreamFormat(stream, &spec, NULL);
  774. if (!ret) {
  775. return -1;
  776. }
  777. frame_size = SDL_AUDIO_FRAMESIZE(spec);
  778. while (len > 0) {
  779. int n = SDLTest_RandomIntegerInRange(1, 10000) * frame_size;
  780. n = SDL_min(n, len);
  781. ret = SDL_PutAudioStreamData(stream, buf, n);
  782. if (!ret) {
  783. return -1;
  784. }
  785. buf = ((const Uint8*) buf) + n;
  786. len -= n;
  787. }
  788. return 0;
  789. }
  790. /* Read the data in randomly sized chunks */
  791. static int get_audio_data_split(SDL_AudioStream* stream, void* buf, int len) {
  792. SDL_AudioSpec spec;
  793. int frame_size;
  794. int ret = SDL_GetAudioStreamFormat(stream, NULL, &spec);
  795. int total = 0;
  796. if (!ret) {
  797. return -1;
  798. }
  799. frame_size = SDL_AUDIO_FRAMESIZE(spec);
  800. while (len > 0) {
  801. int n = SDLTest_RandomIntegerInRange(1, 10000) * frame_size;
  802. n = SDL_min(n, len);
  803. ret = SDL_GetAudioStreamData(stream, buf, n);
  804. if (ret <= 0) {
  805. return total ? total : -1;
  806. }
  807. buf = ((Uint8*) buf) + ret;
  808. total += ret;
  809. len -= ret;
  810. }
  811. return total;
  812. }
  813. /* Convert the data in chunks, putting/getting randomly sized chunks until finished */
  814. static int convert_audio_chunks(SDL_AudioStream* stream, const void* src, int srclen, void* dst, int dstlen)
  815. {
  816. SDL_AudioSpec src_spec, dst_spec;
  817. int src_frame_size, dst_frame_size;
  818. int total_in = 0, total_out = 0;
  819. int ret = SDL_GetAudioStreamFormat(stream, &src_spec, &dst_spec);
  820. if (!ret) {
  821. return -1;
  822. }
  823. src_frame_size = SDL_AUDIO_FRAMESIZE(src_spec);
  824. dst_frame_size = SDL_AUDIO_FRAMESIZE(dst_spec);
  825. while ((total_in < srclen) || (total_out < dstlen)) {
  826. /* Make sure we put in more than the padding frames so we get non-zero output */
  827. const int RESAMPLER_MAX_PADDING_FRAMES = 7; /* Should match RESAMPLER_MAX_PADDING_FRAMES in SDL */
  828. int to_put = SDLTest_RandomIntegerInRange(RESAMPLER_MAX_PADDING_FRAMES + 1, 40000) * src_frame_size;
  829. int to_get = SDLTest_RandomIntegerInRange(1, (int)((40000.0f * dst_spec.freq) / src_spec.freq)) * dst_frame_size;
  830. to_put = SDL_min(to_put, srclen - total_in);
  831. to_get = SDL_min(to_get, dstlen - total_out);
  832. if (to_put)
  833. {
  834. ret = put_audio_data_split(stream, (const Uint8*)(src) + total_in, to_put);
  835. if (ret < 0) {
  836. return total_out ? total_out : ret;
  837. }
  838. total_in += to_put;
  839. if (total_in == srclen) {
  840. ret = SDL_FlushAudioStream(stream);
  841. if (!ret) {
  842. return total_out ? total_out : -1;
  843. }
  844. }
  845. }
  846. if (to_get)
  847. {
  848. ret = get_audio_data_split(stream, (Uint8*)(dst) + total_out, to_get);
  849. if ((ret == 0) && (total_in == srclen)) {
  850. ret = -1;
  851. }
  852. if (ret < 0) {
  853. return total_out ? total_out : ret;
  854. }
  855. total_out += ret;
  856. }
  857. }
  858. return total_out;
  859. }
  860. /**
  861. * Check signal-to-noise ratio and maximum error of audio resampling.
  862. *
  863. * \sa https://wiki.libsdl.org/SDL_CreateAudioStream
  864. * \sa https://wiki.libsdl.org/SDL_DestroyAudioStream
  865. * \sa https://wiki.libsdl.org/SDL_PutAudioStreamData
  866. * \sa https://wiki.libsdl.org/SDL_FlushAudioStream
  867. * \sa https://wiki.libsdl.org/SDL_GetAudioStreamData
  868. */
  869. static int SDLCALL audio_resampleLoss(void *arg)
  870. {
  871. /* Note: always test long input time (>= 5s from experience) in some test
  872. * cases because an improper implementation may suffer from low resampling
  873. * precision with long input due to e.g. doing subtraction with large floats. */
  874. struct test_spec_t {
  875. int time;
  876. int freq;
  877. double phase;
  878. int rate_in;
  879. int rate_out;
  880. double signal_to_noise;
  881. double max_error;
  882. } test_specs[] = {
  883. { 50, 440, 0, 44100, 48000, 80, 0.0010 },
  884. { 50, 5000, SDL_PI_D / 2, 20000, 10000, 999, 0.0001 },
  885. { 50, 440, 0, 22050, 96000, 79, 0.0120 },
  886. { 50, 440, 0, 96000, 22050, 80, 0.0002 },
  887. { 0 }
  888. };
  889. int spec_idx = 0;
  890. int min_channels = 1;
  891. int max_channels = 1 /*8*/;
  892. int num_channels = min_channels;
  893. for (spec_idx = 0; test_specs[spec_idx].time > 0;) {
  894. const struct test_spec_t *spec = &test_specs[spec_idx];
  895. const int frames_in = spec->time * spec->rate_in;
  896. const int frames_target = spec->time * spec->rate_out;
  897. const int len_in = (frames_in * num_channels) * (int)sizeof(float);
  898. const int len_target = (frames_target * num_channels) * (int)sizeof(float);
  899. const int max_target = len_target * 2;
  900. SDL_AudioSpec tmpspec1, tmpspec2;
  901. Uint64 tick_beg = 0;
  902. Uint64 tick_end = 0;
  903. int i = 0;
  904. int j = 0;
  905. SDL_AudioStream *stream = NULL;
  906. float *buf_in = NULL;
  907. float *buf_out = NULL;
  908. int len_out = 0;
  909. double max_error = 0;
  910. double sum_squared_error = 0;
  911. double sum_squared_value = 0;
  912. double signal_to_noise = 0;
  913. SDL_zero(tmpspec1);
  914. SDL_zero(tmpspec2);
  915. SDLTest_AssertPass("Test resampling of %i s %i Hz %f phase sine wave from sampling rate of %i Hz to %i Hz",
  916. spec->time, spec->freq, spec->phase, spec->rate_in, spec->rate_out);
  917. tmpspec1.format = SDL_AUDIO_F32;
  918. tmpspec1.channels = num_channels;
  919. tmpspec1.freq = spec->rate_in;
  920. tmpspec2.format = SDL_AUDIO_F32;
  921. tmpspec2.channels = num_channels;
  922. tmpspec2.freq = spec->rate_out;
  923. stream = SDL_CreateAudioStream(&tmpspec1, &tmpspec2);
  924. SDLTest_AssertPass("Call to SDL_CreateAudioStream(SDL_AUDIO_F32, %i, %i, SDL_AUDIO_F32, %i, %i)", num_channels, spec->rate_in, num_channels, spec->rate_out);
  925. SDLTest_AssertCheck(stream != NULL, "Expected SDL_CreateAudioStream to succeed.");
  926. if (stream == NULL) {
  927. return TEST_ABORTED;
  928. }
  929. buf_in = (float *)SDL_malloc(len_in);
  930. SDLTest_AssertCheck(buf_in != NULL, "Expected input buffer to be created.");
  931. if (buf_in == NULL) {
  932. SDL_DestroyAudioStream(stream);
  933. return TEST_ABORTED;
  934. }
  935. for (i = 0; i < frames_in; ++i) {
  936. float f = (float)sine_wave_sample(i, spec->rate_in, spec->freq, spec->phase);
  937. for (j = 0; j < num_channels; ++j) {
  938. *(buf_in + (i * num_channels) + j) = f;
  939. }
  940. }
  941. tick_beg = SDL_GetPerformanceCounter();
  942. buf_out = (float *)SDL_malloc(max_target);
  943. SDLTest_AssertCheck(buf_out != NULL, "Expected output buffer to be created.");
  944. if (buf_out == NULL) {
  945. SDL_DestroyAudioStream(stream);
  946. return TEST_ABORTED;
  947. }
  948. len_out = convert_audio_chunks(stream, buf_in, len_in, buf_out, max_target);
  949. SDLTest_AssertPass("Call to convert_audio_chunks(stream, buf_in, %i, buf_out, %i)", len_in, len_target);
  950. SDLTest_AssertCheck(len_out == len_target, "Expected output length to be %i, got %i.",
  951. len_target, len_out);
  952. SDL_free(buf_in);
  953. if (len_out != len_target) {
  954. SDL_DestroyAudioStream(stream);
  955. return TEST_ABORTED;
  956. }
  957. tick_end = SDL_GetPerformanceCounter();
  958. SDLTest_Log("Resampling used %f seconds.", ((double)(tick_end - tick_beg)) / SDL_GetPerformanceFrequency());
  959. for (i = 0; i < frames_target; ++i) {
  960. const double target = sine_wave_sample(i, spec->rate_out, spec->freq, spec->phase);
  961. for (j = 0; j < num_channels; ++j) {
  962. const float output = *(buf_out + (i * num_channels) + j);
  963. const double error = SDL_fabs(target - output);
  964. max_error = SDL_max(max_error, error);
  965. sum_squared_error += error * error;
  966. sum_squared_value += target * target;
  967. }
  968. }
  969. SDL_free(buf_out);
  970. signal_to_noise = 10 * SDL_log10(sum_squared_value / sum_squared_error); /* decibel */
  971. SDLTest_AssertCheck(ISFINITE(sum_squared_value), "Sum of squared target should be finite.");
  972. SDLTest_AssertCheck(ISFINITE(sum_squared_error), "Sum of squared error should be finite.");
  973. /* Infinity is theoretically possible when there is very little to no noise */
  974. SDLTest_AssertCheck(!ISNAN(signal_to_noise), "Signal-to-noise ratio should not be NaN.");
  975. SDLTest_AssertCheck(ISFINITE(max_error), "Maximum conversion error should be finite.");
  976. SDLTest_AssertCheck(signal_to_noise >= spec->signal_to_noise, "Conversion signal-to-noise ratio %f dB should be no less than %f dB.",
  977. signal_to_noise, spec->signal_to_noise);
  978. SDLTest_AssertCheck(max_error <= spec->max_error, "Maximum conversion error %f should be no more than %f.",
  979. max_error, spec->max_error);
  980. if (++num_channels > max_channels) {
  981. num_channels = min_channels;
  982. ++spec_idx;
  983. }
  984. }
  985. return TEST_COMPLETED;
  986. }
  987. /**
  988. * Check accuracy converting between audio formats.
  989. *
  990. * \sa SDL_ConvertAudioSamples
  991. */
  992. static int SDLCALL audio_convertAccuracy(void *arg)
  993. {
  994. static SDL_AudioFormat formats[] = { SDL_AUDIO_S8, SDL_AUDIO_U8, SDL_AUDIO_S16, SDL_AUDIO_S32 };
  995. static const char* format_names[] = { "S8", "U8", "S16", "S32" };
  996. int src_num = 65537 + 2048 + 48 + 256 + 100000;
  997. int src_len = src_num * sizeof(float);
  998. float* src_data = SDL_malloc(src_len);
  999. int i, j;
  1000. SDLTest_AssertCheck(src_data != NULL, "Expected source buffer to be created.");
  1001. if (src_data == NULL) {
  1002. return TEST_ABORTED;
  1003. }
  1004. j = 0;
  1005. /* Generate a uniform range of floats between [-1.0, 1.0] */
  1006. for (i = 0; i < 65537; ++i) {
  1007. src_data[j++] = ((float)i - 32768.0f) / 32768.0f;
  1008. }
  1009. /* Generate floats close to 1.0 */
  1010. const float max_val = 16777216.0f;
  1011. for (i = 0; i < 1024; ++i) {
  1012. float f = (max_val + (float)(512 - i)) / max_val;
  1013. src_data[j++] = f;
  1014. src_data[j++] = -f;
  1015. }
  1016. for (i = 0; i < 24; ++i) {
  1017. float f = (max_val + (float)(3u << i)) / max_val;
  1018. src_data[j++] = f;
  1019. src_data[j++] = -f;
  1020. }
  1021. /* Generate floats far outside the [-1.0, 1.0] range */
  1022. for (i = 0; i < 128; ++i) {
  1023. float f = 2.0f + (float) i;
  1024. src_data[j++] = f;
  1025. src_data[j++] = -f;
  1026. }
  1027. /* Fill the rest with random floats between [-1.0, 1.0] */
  1028. for (i = 0; i < 100000; ++i) {
  1029. src_data[j++] = SDLTest_RandomSint32() / 2147483648.0f;
  1030. }
  1031. /* Shuffle the data for good measure */
  1032. for (i = src_num - 1; i > 0; --i) {
  1033. float f = src_data[i];
  1034. j = SDLTest_RandomIntegerInRange(0, i);
  1035. src_data[i] = src_data[j];
  1036. src_data[j] = f;
  1037. }
  1038. for (i = 0; i < SDL_arraysize(formats); ++i) {
  1039. SDL_AudioSpec src_spec, tmp_spec;
  1040. Uint64 convert_begin, convert_end;
  1041. Uint8 *tmp_data, *dst_data;
  1042. int tmp_len, dst_len;
  1043. int ret;
  1044. SDL_zero(src_spec);
  1045. SDL_zero(tmp_spec);
  1046. SDL_AudioFormat format = formats[i];
  1047. const char* format_name = format_names[i];
  1048. /* Formats with > 23 bits can represent every value exactly */
  1049. float min_delta = 1.0f;
  1050. float max_delta = -1.0f;
  1051. /* Subtract 1 bit to account for sign */
  1052. int bits = SDL_AUDIO_BITSIZE(format) - 1;
  1053. float target_max_delta = (bits > 23) ? 0.0f : (1.0f / (float)(1 << bits));
  1054. float target_min_delta = -target_max_delta;
  1055. src_spec.format = SDL_AUDIO_F32;
  1056. src_spec.channels = 1;
  1057. src_spec.freq = 44100;
  1058. tmp_spec.format = format;
  1059. tmp_spec.channels = 1;
  1060. tmp_spec.freq = 44100;
  1061. convert_begin = SDL_GetPerformanceCounter();
  1062. tmp_data = NULL;
  1063. tmp_len = 0;
  1064. ret = SDL_ConvertAudioSamples(&src_spec, (const Uint8*) src_data, src_len, &tmp_spec, &tmp_data, &tmp_len);
  1065. SDLTest_AssertCheck(ret == true, "Expected SDL_ConvertAudioSamples(F32->%s) to succeed", format_name);
  1066. if (!ret) {
  1067. SDL_free(src_data);
  1068. return TEST_ABORTED;
  1069. }
  1070. dst_data = NULL;
  1071. dst_len = 0;
  1072. ret = SDL_ConvertAudioSamples(&tmp_spec, tmp_data, tmp_len, &src_spec, &dst_data, &dst_len);
  1073. SDLTest_AssertCheck(ret == true, "Expected SDL_ConvertAudioSamples(%s->F32) to succeed", format_name);
  1074. if (!ret) {
  1075. SDL_free(tmp_data);
  1076. SDL_free(src_data);
  1077. return TEST_ABORTED;
  1078. }
  1079. convert_end = SDL_GetPerformanceCounter();
  1080. SDLTest_Log("Conversion via %s took %f seconds.", format_name, ((double)(convert_end - convert_begin)) / SDL_GetPerformanceFrequency());
  1081. SDL_free(tmp_data);
  1082. for (j = 0; j < src_num; ++j) {
  1083. float x = src_data[j];
  1084. float y = ((float*)dst_data)[j];
  1085. float d = SDL_clamp(x, -1.0f, 1.0f) - y;
  1086. min_delta = SDL_min(min_delta, d);
  1087. max_delta = SDL_max(max_delta, d);
  1088. }
  1089. SDLTest_AssertCheck(min_delta >= target_min_delta, "%s has min delta of %+f, should be >= %+f", format_name, min_delta, target_min_delta);
  1090. SDLTest_AssertCheck(max_delta <= target_max_delta, "%s has max delta of %+f, should be <= %+f", format_name, max_delta, target_max_delta);
  1091. SDL_free(dst_data);
  1092. }
  1093. SDL_free(src_data);
  1094. return TEST_COMPLETED;
  1095. }
  1096. /**
  1097. * Check accuracy when switching between formats
  1098. *
  1099. * \sa SDL_SetAudioStreamFormat
  1100. */
  1101. static int SDLCALL audio_formatChange(void *arg)
  1102. {
  1103. int i;
  1104. SDL_AudioSpec spec1, spec2, spec3;
  1105. int frames_1, frames_2, frames_3;
  1106. int length_1, length_2, length_3;
  1107. int result = 0;
  1108. int status = TEST_ABORTED;
  1109. float* buffer_1 = NULL;
  1110. float* buffer_2 = NULL;
  1111. float* buffer_3 = NULL;
  1112. SDL_AudioStream* stream = NULL;
  1113. double max_error = 0;
  1114. double sum_squared_error = 0;
  1115. double sum_squared_value = 0;
  1116. double signal_to_noise = 0;
  1117. double target_max_error = 0.02;
  1118. double target_signal_to_noise = 75.0;
  1119. int sine_freq = 500;
  1120. SDL_zero(spec1);
  1121. SDL_zero(spec2);
  1122. SDL_zero(spec3);
  1123. spec1.format = SDL_AUDIO_F32;
  1124. spec1.channels = 1;
  1125. spec1.freq = 20000;
  1126. spec2.format = SDL_AUDIO_F32;
  1127. spec2.channels = 1;
  1128. spec2.freq = 40000;
  1129. spec3.format = SDL_AUDIO_F32;
  1130. spec3.channels = 1;
  1131. spec3.freq = 80000;
  1132. frames_1 = spec1.freq;
  1133. frames_2 = spec2.freq;
  1134. frames_3 = spec3.freq * 2;
  1135. length_1 = (int)(frames_1 * sizeof(*buffer_1));
  1136. buffer_1 = (float*) SDL_malloc(length_1);
  1137. if (!SDLTest_AssertCheck(buffer_1 != NULL, "Expected buffer_1 to be created.")) {
  1138. goto cleanup;
  1139. }
  1140. length_2 = (int)(frames_2 * sizeof(*buffer_2));
  1141. buffer_2 = (float*) SDL_malloc(length_2);
  1142. if (!SDLTest_AssertCheck(buffer_2 != NULL, "Expected buffer_2 to be created.")) {
  1143. goto cleanup;
  1144. }
  1145. length_3 = (int)(frames_3 * sizeof(*buffer_3));
  1146. buffer_3 = (float*) SDL_malloc(length_3);
  1147. if (!SDLTest_AssertCheck(buffer_3 != NULL, "Expected buffer_3 to be created.")) {
  1148. goto cleanup;
  1149. }
  1150. for (i = 0; i < frames_1; ++i) {
  1151. buffer_1[i] = (float) sine_wave_sample(i, spec1.freq, sine_freq, 0.0f);
  1152. }
  1153. for (i = 0; i < frames_2; ++i) {
  1154. buffer_2[i] = (float) sine_wave_sample(i, spec2.freq, sine_freq, 0.0f);
  1155. }
  1156. stream = SDL_CreateAudioStream(NULL, NULL);
  1157. if (!SDLTest_AssertCheck(stream != NULL, "Expected SDL_CreateAudioStream to succeed")) {
  1158. goto cleanup;
  1159. }
  1160. result = SDL_SetAudioStreamFormat(stream, &spec1, &spec3);
  1161. if (!SDLTest_AssertCheck(result == true, "Expected SDL_SetAudioStreamFormat(spec1, spec3) to succeed")) {
  1162. goto cleanup;
  1163. }
  1164. result = SDL_GetAudioStreamAvailable(stream);
  1165. if (!SDLTest_AssertCheck(result == 0, "Expected SDL_GetAudioStreamAvailable return 0")) {
  1166. goto cleanup;
  1167. }
  1168. result = SDL_PutAudioStreamData(stream, buffer_1, length_1);
  1169. if (!SDLTest_AssertCheck(result == true, "Expected SDL_PutAudioStreamData(buffer_1) to succeed")) {
  1170. goto cleanup;
  1171. }
  1172. result = SDL_FlushAudioStream(stream);
  1173. if (!SDLTest_AssertCheck(result == true, "Expected SDL_FlushAudioStream to succeed")) {
  1174. goto cleanup;
  1175. }
  1176. result = SDL_SetAudioStreamFormat(stream, &spec2, &spec3);
  1177. if (!SDLTest_AssertCheck(result == true, "Expected SDL_SetAudioStreamFormat(spec2, spec3) to succeed")) {
  1178. goto cleanup;
  1179. }
  1180. result = SDL_PutAudioStreamData(stream, buffer_2, length_2);
  1181. if (!SDLTest_AssertCheck(result == true, "Expected SDL_PutAudioStreamData(buffer_1) to succeed")) {
  1182. goto cleanup;
  1183. }
  1184. result = SDL_FlushAudioStream(stream);
  1185. if (!SDLTest_AssertCheck(result == true, "Expected SDL_FlushAudioStream to succeed")) {
  1186. goto cleanup;
  1187. }
  1188. result = SDL_GetAudioStreamAvailable(stream);
  1189. if (!SDLTest_AssertCheck(result == length_3, "Expected SDL_GetAudioStreamAvailable to return %i, got %i", length_3, result)) {
  1190. goto cleanup;
  1191. }
  1192. result = SDL_GetAudioStreamData(stream, buffer_3, length_3);
  1193. if (!SDLTest_AssertCheck(result == length_3, "Expected SDL_GetAudioStreamData to return %i, got %i", length_3, result)) {
  1194. goto cleanup;
  1195. }
  1196. result = SDL_GetAudioStreamAvailable(stream);
  1197. if (!SDLTest_AssertCheck(result == 0, "Expected SDL_GetAudioStreamAvailable to return 0")) {
  1198. goto cleanup;
  1199. }
  1200. for (i = 0; i < frames_3; ++i) {
  1201. const float output = buffer_3[i];
  1202. const float target = (float) sine_wave_sample(i, spec3.freq, sine_freq, 0.0f);
  1203. const double error = SDL_fabs(target - output);
  1204. max_error = SDL_max(max_error, error);
  1205. sum_squared_error += error * error;
  1206. sum_squared_value += target * target;
  1207. }
  1208. signal_to_noise = 10 * SDL_log10(sum_squared_value / sum_squared_error); /* decibel */
  1209. SDLTest_AssertCheck(ISFINITE(sum_squared_value), "Sum of squared target should be finite.");
  1210. SDLTest_AssertCheck(ISFINITE(sum_squared_error), "Sum of squared error should be finite.");
  1211. /* Infinity is theoretically possible when there is very little to no noise */
  1212. SDLTest_AssertCheck(!ISNAN(signal_to_noise), "Signal-to-noise ratio should not be NaN.");
  1213. SDLTest_AssertCheck(ISFINITE(max_error), "Maximum conversion error should be finite.");
  1214. SDLTest_AssertCheck(signal_to_noise >= target_signal_to_noise, "Conversion signal-to-noise ratio %f dB should be no less than %f dB.",
  1215. signal_to_noise, target_signal_to_noise);
  1216. SDLTest_AssertCheck(max_error <= target_max_error, "Maximum conversion error %f should be no more than %f.",
  1217. max_error, target_max_error);
  1218. status = TEST_COMPLETED;
  1219. cleanup:
  1220. SDL_free(buffer_1);
  1221. SDL_free(buffer_2);
  1222. SDL_free(buffer_3);
  1223. SDL_DestroyAudioStream(stream);
  1224. return status;
  1225. }
  1226. /* ================= Test Case References ================== */
  1227. /* Audio test cases */
  1228. static const SDLTest_TestCaseReference audioTestGetAudioFormatName = {
  1229. audio_getAudioFormatName, "audio_getAudioFormatName", "Call to SDL_GetAudioFormatName", TEST_ENABLED
  1230. };
  1231. static const SDLTest_TestCaseReference audioTest1 = {
  1232. audio_enumerateAndNameAudioDevices, "audio_enumerateAndNameAudioDevices", "Enumerate and name available audio devices (playback and recording)", TEST_ENABLED
  1233. };
  1234. static const SDLTest_TestCaseReference audioTest2 = {
  1235. audio_enumerateAndNameAudioDevicesNegativeTests, "audio_enumerateAndNameAudioDevicesNegativeTests", "Negative tests around enumeration and naming of audio devices.", TEST_ENABLED
  1236. };
  1237. static const SDLTest_TestCaseReference audioTest3 = {
  1238. audio_printAudioDrivers, "audio_printAudioDrivers", "Checks available audio driver names.", TEST_ENABLED
  1239. };
  1240. static const SDLTest_TestCaseReference audioTest4 = {
  1241. audio_printCurrentAudioDriver, "audio_printCurrentAudioDriver", "Checks current audio driver name with initialized audio.", TEST_ENABLED
  1242. };
  1243. static const SDLTest_TestCaseReference audioTest5 = {
  1244. audio_buildAudioStream, "audio_buildAudioStream", "Builds various audio conversion structures.", TEST_ENABLED
  1245. };
  1246. static const SDLTest_TestCaseReference audioTest6 = {
  1247. audio_buildAudioStreamNegative, "audio_buildAudioStreamNegative", "Checks calls with invalid input to SDL_CreateAudioStream", TEST_ENABLED
  1248. };
  1249. static const SDLTest_TestCaseReference audioTest7 = {
  1250. audio_getAudioStatus, "audio_getAudioStatus", "Checks current audio status.", TEST_ENABLED
  1251. };
  1252. static const SDLTest_TestCaseReference audioTest8 = {
  1253. audio_openCloseAndGetAudioStatus, "audio_openCloseAndGetAudioStatus", "Opens and closes audio device and get audio status.", TEST_ENABLED
  1254. };
  1255. static const SDLTest_TestCaseReference audioTest9 = {
  1256. audio_lockUnlockOpenAudioDevice, "audio_lockUnlockOpenAudioDevice", "Locks and unlocks an open audio device.", TEST_ENABLED
  1257. };
  1258. static const SDLTest_TestCaseReference audioTest10 = {
  1259. audio_convertAudio, "audio_convertAudio", "Convert audio using available formats.", TEST_ENABLED
  1260. };
  1261. /* TODO: enable test when SDL_AudioDeviceConnected has been implemented. */
  1262. static const SDLTest_TestCaseReference audioTest11 = {
  1263. audio_openCloseAudioDeviceConnected, "audio_openCloseAudioDeviceConnected", "Opens and closes audio device and get connected status.", TEST_DISABLED
  1264. };
  1265. static const SDLTest_TestCaseReference audioTest12 = {
  1266. audio_quitInitAudioSubSystem, "audio_quitInitAudioSubSystem", "Quit and re-init audio subsystem.", TEST_ENABLED
  1267. };
  1268. static const SDLTest_TestCaseReference audioTest13 = {
  1269. audio_initQuitAudio, "audio_initQuitAudio", "Init and quit audio drivers directly.", TEST_ENABLED
  1270. };
  1271. static const SDLTest_TestCaseReference audioTest14 = {
  1272. audio_initOpenCloseQuitAudio, "audio_initOpenCloseQuitAudio", "Cycle through init, open, close and quit with various audio specs.", TEST_ENABLED
  1273. };
  1274. static const SDLTest_TestCaseReference audioTest15 = {
  1275. audio_pauseUnpauseAudio, "audio_pauseUnpauseAudio", "Pause and Unpause audio for various audio specs while testing callback.", TEST_ENABLED
  1276. };
  1277. static const SDLTest_TestCaseReference audioTest16 = {
  1278. audio_resampleLoss, "audio_resampleLoss", "Check signal-to-noise ratio and maximum error of audio resampling.", TEST_ENABLED
  1279. };
  1280. static const SDLTest_TestCaseReference audioTest17 = {
  1281. audio_convertAccuracy, "audio_convertAccuracy", "Check accuracy converting between audio formats.", TEST_ENABLED
  1282. };
  1283. static const SDLTest_TestCaseReference audioTest18 = {
  1284. audio_formatChange, "audio_formatChange", "Check handling of format changes.", TEST_ENABLED
  1285. };
  1286. /* Sequence of Audio test cases */
  1287. static const SDLTest_TestCaseReference *audioTests[] = {
  1288. &audioTestGetAudioFormatName,
  1289. &audioTest1, &audioTest2, &audioTest3, &audioTest4, &audioTest5, &audioTest6,
  1290. &audioTest7, &audioTest8, &audioTest9, &audioTest10, &audioTest11,
  1291. &audioTest12, &audioTest13, &audioTest14, &audioTest15, &audioTest16,
  1292. &audioTest17, &audioTest18, NULL
  1293. };
  1294. /* Audio test suite (global) */
  1295. SDLTest_TestSuiteReference audioTestSuite = {
  1296. "Audio",
  1297. audioSetUp,
  1298. audioTests,
  1299. audioTearDown
  1300. };